11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For the STS-Thompson TDA7432 audio processor chip 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handles audio functions: volume, balance, tone, loudness 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver will not complain if used with any 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other i2c device with the same address. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Muting and tone control by Jonathan Isom <jisom@ematic.com> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com> 117a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is placed under the terms of the GNU General Public License 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Which was based on tda8425.c by Greg Alexander (c) 1998 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OPTIONS: 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * debug - set to 1 if you'd like to see debug messages 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set to 2 if you'd like to be inundated with debug messages 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * loudness - set between 0 and 15 for varying degrees of loudness effect 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * maxvol - set maximium volume to +20db (1), default is 0db(0) 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 3333b687cf1df62bd83167616516922b4e472be662Hans Verkuil#include <linux/videodev2.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil#include <media/v4l2-device.h> 3735ea11ff84719b1bfab2909903a9640a86552fd1Hans Verkuil#include <media/v4l2-ioctl.h> 38fa3fcceb30eb8a3cb2ac299c207c6f89b9aed379Mauro Carvalho Chehab#include <media/i2c-addr.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef VIDEO_AUDIO_BALANCE 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define VIDEO_AUDIO_BALANCE 32 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>"); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip"); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maxvol; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int loudness; /* disable loudness by default */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug; /* insmod parameter */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, S_IRUGO | S_IWUSR); 527ce338d9dfc432b71db15184ad3ec458c9961164Hans Petter SelaskyMODULE_PARM_DESC(debug, "Set debugging level from 0 to 3. Default is off(0)."); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(loudness, int, S_IRUGO); 547ce338d9dfc432b71db15184ad3ec458c9961164Hans Petter SelaskyMODULE_PARM_DESC(loudness, "Turn loudness on(1) else off(0). Default is off(0)."); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(maxvol, int, S_IRUGO | S_IWUSR); 567ce338d9dfc432b71db15184ad3ec458c9961164Hans Petter SelaskyMODULE_PARM_DESC(maxvol, "Set maximium volume to +20dB(0) else +0dB(1). Default is +20dB(0)."); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Structure of address and subaddresses for the tda7432 */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct tda7432 { 62d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct v4l2_subdev sd; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int addr; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int input; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int volume; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int muted; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bass, treble; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int lf, lr, rf, rr; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int loud; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 71d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 72d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic inline struct tda7432 *to_state(struct v4l2_subdev *sd) 73d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil{ 74d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil return container_of(sd, struct tda7432, sd); 75d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil} 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The TDA7432 is made by STS-Thompson 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://www.st.com 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://us.st.com/stonline/books/pdf/docs/4056.pdf 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TDA7432: I2C-bus controlled basic audio processor 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The TDA7432 controls basic audio functions like volume, balance, 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and tone control (including loudness). It also has four channel 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * output (for front and rear). Since most vidcap cards probably 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * don't have 4 channel output, this driver will set front & rear 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * together (no independent control). 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Subaddresses for TDA7432 */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_IN 0x00 /* Input select */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_VL 0x01 /* Volume */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_TN 0x02 /* Bass, Treble (Tone) */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_LF 0x03 /* Attenuation LF (Left Front) */ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_LR 0x04 /* Attenuation LR (Left Rear) */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_RF 0x05 /* Attenuation RF (Right Front) */ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_RR 0x06 /* Attenuation RR (Right Rear) */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_LD 0x07 /* Loudness */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Masks for bits in TDA7432 subaddresses */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Many of these not used - just for documentation */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x00 - Input selection and bass control */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits 0,1,2 control input: 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x00 - Stereo input 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x02 - Mono input 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x03 - Mute (Using Attenuators Plays better with modules) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mono probably isn't used - I'm guessing only the stereo 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * input is connected on most cards, so we'll set it to stereo. 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 4 controls bass range: 0/1 is extended/standard bass range 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Highest 3 bits not used 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_STEREO_IN 0 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_MONO_IN 2 /* Probably won't be used */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_BASS_SYM 1 << 3 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_BASS_NORM 1 << 4 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x01 - Volume */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Recommended maximum is +20 dB 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * +32dB: 0x00 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * +20dB: 0x0c 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0dB: 0x20 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -79dB: 0x6f 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MSB (bit 7) controls loudness: 1/0 is loudness on/off 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_VOL_0DB 0x20 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_LD_ON 1 << 7 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x02 - Tone control */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x0 is 14dB, 0x7 is 0dB 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 3 controls treble attenuation/gain (sign) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 = gain (+) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 = attenuation (-) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bits 4,5,6 control absolute bass gain from 0dB to 14dB 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (This is only true for normal base range, set in 0x00) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x0 << 4 is 14dB, 0x7 is 0dB 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 7 controls bass attenuation/gain (sign) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 << 7 = gain (+) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 << 7 = attenuation (-) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Example: 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_TREBLE_0DB 0xf 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_TREBLE 7 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_TREBLE_GAIN 1 << 3 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_BASS_0DB 0xf 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_BASS 7 << 4 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_BASS_GAIN 1 << 7 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x03 - Left Front attenuation */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x04 - Left Rear attenuation */ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x05 - Right Front attenuation */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x06 - Right Rear attenuation */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in 1.5dB steps. 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x00 is 0dB 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x1f is -37.5dB 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 5 mutes that channel when set (1 = mute, 0 = unmute) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We'll use the mute on the input, though (above) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bits 6,7 unused 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_ATTEN_0DB 0x00 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA7432_MUTE 0x1 << 5 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Subaddress 0x07 - Loudness Control */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when bit 4 is NOT set 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x0 is 0dB 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0xf is -15dB 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If bit 4 is set, then there is a flat attenuation according to 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the lower 4 bits, as above. 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bits 5,6,7 unused 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Begin code */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 210d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 212d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char buffer[2]; 214d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 215d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_dbg(2, debug, sd, "In tda7432_write\n"); 216d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer[0] = subaddr; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer[1] = val; 219d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil if (2 != i2c_master_send(client, buffer, 2)) { 220d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_err(sd, "I/O error, trying (write %d 0x%x)\n", 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subaddr, val); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 227d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_set(struct v4l2_subdev *sd) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 229d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 230d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct tda7432 *t = to_state(sd); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char buf[16]; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_dbg(1, debug, sd, 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", 235d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil t->input, t->volume, t->bass, t->treble, t->lf, t->lr, 236d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil t->rf, t->rr, t->loud); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = TDA7432_IN; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[1] = t->input; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[2] = t->volume; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[3] = t->bass; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = t->treble; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = t->lf; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[6] = t->lr; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[7] = t->rf; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[8] = t->rr; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[9] = t->loud; 247d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil if (10 != i2c_master_send(client, buf, 10)) { 248d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_err(sd, "I/O error, trying tda7432_set\n"); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 255d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic void do_tda7432_init(struct v4l2_subdev *sd) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 257d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct tda7432 *t = to_state(sd); 258d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 259d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_dbg(2, debug, sd, "In tda7432_init\n"); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TDA7432_BASS_SYM | /* Symmetric bass cut */ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TDA7432_BASS_NORM; /* Normal bass range */ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->volume = 0x3b ; /* -27dB Volume */ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (loudness) /* Turn loudness on? */ 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->volume |= TDA7432_LD_ON; 2677a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->muted = 1; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->treble = TDA7432_TREBLE_0DB; /* 0dB Treble */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->bass = TDA7432_BASS_0DB; /* 0dB Bass */ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->loud = loudness; /* insmod parameter */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 276d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_set(sd); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 279d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 281d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct tda7432 *t = to_state(sd); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2837a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab switch (ctrl->id) { 2847a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_MUTE: 2857a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value=t->muted; 2867a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 2877a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_VOLUME: 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!maxvol){ /* max +20db */ 2897a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 630; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* max 0db */ 2917a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 829; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2937a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 2947a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_BALANCE: 2957a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab { 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( (t->lf) < (t->rf) ) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* right is attenuated, balance shifted left */ 2987a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value = (32768 - 1057*(t->rf)); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* left is attenuated, balance shifted right */ 3017a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value = (32768 + 1057*(t->lf)); 3027a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3037a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 3047a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_BASS: 3057a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab { 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Bass/treble 4 bits each */ 3077a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab int bass=t->bass; 3087a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if(bass >= 0x8) 3097a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab bass = ~(bass - 0x8) & 0xf; 3107a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value = (bass << 12)+(bass << 8)+(bass << 4)+(bass); 3117a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3137a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_TREBLE: 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3157a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab int treble=t->treble; 3167a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if(treble >= 0x8) 3177a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab treble = ~(treble - 0x8) & 0xf; 3187a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab ctrl->value = (treble << 12)+(treble << 8)+(treble << 4)+(treble); 3197a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3207a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 3217a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 3227a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return -EINVAL; 3237a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab} 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 325d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 3267a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab{ 327d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct tda7432 *t = to_state(sd); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3297a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab switch (ctrl->id) { 3307a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_MUTE: 3317a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->muted=ctrl->value; 3327a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab break; 3337a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_VOLUME: 3347a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if(!maxvol){ /* max +20db */ 3357a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->volume = 0x6f - ((ctrl->value)/630); 3367a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } else { /* max 0db */ 3377a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->volume = 0x6f - ((ctrl->value)/829); 3387a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (loudness) /* Turn on the loudness bit */ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->volume |= TDA7432_LD_ON; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 342d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_VL, t->volume); 3437a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3447a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_BALANCE: 3457a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if (ctrl->value < 32768) { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* shifted to left, attenuate right */ 3477a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->rr = (32768 - ctrl->value)/1057; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rf = t->rr; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lr = TDA7432_ATTEN_0DB; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lf = TDA7432_ATTEN_0DB; 3517a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } else if(ctrl->value > 32769) { 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* shifted to right, attenuate left */ 3537a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->lf = (ctrl->value - 32768)/1057; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lr = t->lf; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rr = TDA7432_ATTEN_0DB; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rf = TDA7432_ATTEN_0DB; 3577a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } else { 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* centered */ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rr = TDA7432_ATTEN_0DB; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->rf = TDA7432_ATTEN_0DB; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lf = TDA7432_ATTEN_0DB; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->lr = TDA7432_ATTEN_0DB; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3647a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab break; 3657a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_BASS: 3667a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->bass = ctrl->value >> 12; 3677a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if(t->bass>= 0x8) 3687a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->bass = (~t->bass & 0xf) + 0x8 ; 3697a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab 370d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble); 3717a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3727a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab case V4L2_CID_AUDIO_TREBLE: 3737a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->treble= ctrl->value >> 12; 3747a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if(t->treble>= 0x8) 3757a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab t->treble = (~t->treble & 0xf) + 0x8 ; 3767a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab 377d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble); 3787a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3797a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab default: 3807a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return -EINVAL; 3817a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3837a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab /* Used for both mute and balance changes */ 3847a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab if (t->muted) 3857a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab { 3867a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab /* Mute & update balance*/ 387d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_LF, t->lf | TDA7432_MUTE); 388d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_LR, t->lr | TDA7432_MUTE); 389d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_RF, t->rf | TDA7432_MUTE); 390d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_RR, t->rr | TDA7432_MUTE); 3917a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } else { 392d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_LF, t->lf); 393d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_LR, t->lr); 394d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_RF, t->rf); 395d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil tda7432_write(sd, TDA7432_RR, t->rr); 3967a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 3977a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab return 0; 3987a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab} 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 400d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) 4017a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab{ 402d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil switch (qc->id) { 403d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil case V4L2_CID_AUDIO_VOLUME: 40410afbef15e7bba5e1008f583852077743d28c395Hans Verkuil return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); 40510afbef15e7bba5e1008f583852077743d28c395Hans Verkuil case V4L2_CID_AUDIO_MUTE: 40610afbef15e7bba5e1008f583852077743d28c395Hans Verkuil return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); 407d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil case V4L2_CID_AUDIO_BALANCE: 408d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil case V4L2_CID_AUDIO_BASS: 409d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil case V4L2_CID_AUDIO_TREBLE: 41010afbef15e7bba5e1008f583852077743d28c395Hans Verkuil return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); 4117a00d45cf017172c74d15bad0f9f14720efd69ddMauro Carvalho Chehab } 412d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil return -EINVAL; 413d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil} 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 415d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil/* ----------------------------------------------------------------------- */ 416d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 417d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic const struct v4l2_subdev_core_ops tda7432_core_ops = { 418d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil .queryctrl = tda7432_queryctrl, 419d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil .g_ctrl = tda7432_g_ctrl, 420d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil .s_ctrl = tda7432_s_ctrl, 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 423d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic const struct v4l2_subdev_ops tda7432_ops = { 424d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil .core = &tda7432_core_ops, 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 427d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil/* ----------------------------------------------------------------------- */ 428d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 429d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil/* *********************** * 430d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil * i2c interface functions * 431d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil * *********************** */ 432d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 433d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_probe(struct i2c_client *client, 434d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil const struct i2c_device_id *id) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 436d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct tda7432 *t; 437d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct v4l2_subdev *sd; 438d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 439d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l_info(client, "chip found @ 0x%02x (%s)\n", 440d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil client->addr << 1, client->adapter->name); 441d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 442d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil t = kzalloc(sizeof(*t), GFP_KERNEL); 443d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil if (!t) 444d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil return -ENOMEM; 445d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil sd = &t->sd; 446d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_i2c_subdev_init(sd, client, &tda7432_ops); 447d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil if (loudness < 0 || loudness > 15) { 448d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_warn(sd, "loudness parameter must be between 0 and 15\n"); 449d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil if (loudness < 0) 450d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil loudness = 0; 451d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil if (loudness > 15) 452d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil loudness = 15; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 455d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil do_tda7432_init(sd); 456d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil return 0; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 459d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic int tda7432_remove(struct i2c_client *client) 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 461d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil struct v4l2_subdev *sd = i2c_get_clientdata(client); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 463d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil do_tda7432_init(sd); 464d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil v4l2_device_unregister_subdev(sd); 465d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil kfree(to_state(sd)); 466d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil return 0; 467d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil} 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 469d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuilstatic const struct i2c_device_id tda7432_id[] = { 470d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil { "tda7432", 0 }, 471d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil { } 472d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil}; 473d531305ae148d5a401f34cd64434824f5cb8c2b1Hans VerkuilMODULE_DEVICE_TABLE(i2c, tda7432_id); 474d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil 4755b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuilstatic struct i2c_driver tda7432_driver = { 4765b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil .driver = { 4775b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil .owner = THIS_MODULE, 4785b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil .name = "tda7432", 4795b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil }, 4805b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil .probe = tda7432_probe, 4815b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil .remove = tda7432_remove, 4825b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil .id_table = tda7432_id, 483d531305ae148d5a401f34cd64434824f5cb8c2b1Hans Verkuil}; 4845b9f80af0c2678e854725640a15b2c7a386ac185Hans Verkuil 485c6e8d86fffd8edf1bfccbd441b1812ee919fe3d5Axel Linmodule_i2c_driver(tda7432_driver); 486