153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* 253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Programming the mspx4xx sound processor family 353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> 553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * what works and what doesn't: 753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * AM-Mono 953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Support for Hauppauge cards added (decoding handled by tuner) added by 1053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Frederic Crozat <fcrozat@mail.dotcom.fr> 1153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * FM-Mono 1353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * should work. The stereo modes are backward compatible to FM-mono, 1453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * therefore FM-Mono should be allways available. 1553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * FM-Stereo (B/G, used in germany) 1753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * should work, with autodetect 1853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * FM-Stereo (satellite) 2053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * should work, no autodetect (i.e. default is mono, but you can 2153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * switch to stereo -- untested) 2253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 2353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * NICAM (B/G, L , used in UK, Scandinavia, Spain and France) 2453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * should work, with autodetect. Support for NICAM was added by 2553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Pekka Pietikainen <pp@netppl.fi> 2653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 2753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * TODO: 2853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * - better SAT support 2953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 3053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch) 3153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * using soundcore instead of OSS 3253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 3353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * This program is free software; you can redistribute it and/or 3453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * modify it under the terms of the GNU General Public License 3553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * as published by the Free Software Foundation; either version 2 3653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * of the License, or (at your option) any later version. 3753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 3853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * This program is distributed in the hope that it will be useful, 3953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of 4053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 4153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * GNU General Public License for more details. 4253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 4353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * You should have received a copy of the GNU General Public License 4453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * along with this program; if not, write to the Free Software 45d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 46d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * 02110-1301, USA. 4753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil */ 4853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 4953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 5053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/kernel.h> 5153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/module.h> 5253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/slab.h> 5353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/i2c.h> 5476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <linux/kthread.h> 5576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <linux/freezer.h> 562c26976d726838878eb8dd1bc91f84df38a05143Mauro Carvalho Chehab#include <linux/videodev2.h> 5776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <media/v4l2-device.h> 5835ea11ff84719b1bfab2909903a9640a86552fd1Hans Verkuil#include <media/v4l2-ioctl.h> 5949965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bcHans Verkuil#include <media/msp3400.h> 6076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <media/tvaudio.h> 6149965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bcHans Verkuil#include "msp3400-driver.h" 6253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 6353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ---------------------------------------------------------------------- */ 6453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 6553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_DESCRIPTION("device driver for msp34xx TV sound processor"); 6653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_AUTHOR("Gerd Knorr"); 6753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_LICENSE("GPL"); 6853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 6953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* module parameters */ 7053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int opmode = OPMODE_AUTO; 71a5ed425cd30c0c2abac4039ae11b38520aa130c2Mauro Carvalho Chehabint msp_debug; /* msp_debug output */ 7290ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool msp_once; /* no continuous stereo monitoring */ 7390ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool msp_amsound; /* hard-wire AM sound at 6.5 Hz (france), 74a5ed425cd30c0c2abac4039ae11b38520aa130c2Mauro Carvalho Chehab the autoscan seems work well only with FM... */ 75d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilint msp_standard = 1; /* Override auto detect of audio msp_standard, 76d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if needed. */ 7790ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool msp_dolby; 7853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 79f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehabint msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual 8053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil (msp34xxg only) 0x00a0-0x03c0 */ 8153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 8253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* read-only */ 8353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilmodule_param(opmode, int, 0444); 8453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 8553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* read-write */ 86d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(once, msp_once, bool, 0644); 87d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(debug, msp_debug, int, 0644); 88d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(stereo_threshold, msp_stereo_thresh, int, 0644); 89d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(standard, msp_standard, int, 0644); 90d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(amsound, msp_amsound, bool, 0644); 91d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(dolby, msp_dolby, bool, 0644); 9253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 9353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Autodetect, 2=Autodetect and autoselect"); 9453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(once, "No continuous stereo monitoring"); 9553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(debug, "Enable debug messages [0-3]"); 9653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo"); 9753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect"); 9853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan"); 9970f23fd66bc821a0e99647f70a809e277cc93c4cJustin P. MattockMODULE_PARM_DESC(dolby, "Activates Dolby processing"); 10053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 10153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ---------------------------------------------------------------------- */ 10253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 10353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* control subaddress */ 10453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#define I2C_MSP_CONTROL 0x00 10553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* demodulator unit subaddress */ 10653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#define I2C_MSP_DEM 0x10 10753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* DSP unit subaddress */ 10853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#define I2C_MSP_DSP 0x12 10953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 11053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 11153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- */ 11253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* functions for talking to the MSP3400C Sound processor */ 11353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 11453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_reset(struct i2c_client *client) 11553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 11653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* reset and read revision code */ 11753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 }; 11853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil static u8 reset_on[3] = { I2C_MSP_CONTROL, 0x00, 0x00 }; 11953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil static u8 write[3] = { I2C_MSP_DSP + 1, 0x00, 0x1e }; 12053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil u8 read[2]; 12153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil struct i2c_msg reset[2] = { 1221215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D { 1231215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .addr = client->addr, 1241215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .flags = I2C_M_IGNORE_NAK, 1251215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .len = 3, 1261215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .buf = reset_off 1271215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D }, 1281215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D { 1291215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .addr = client->addr, 1301215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .flags = I2C_M_IGNORE_NAK, 1311215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .len = 3, 1321215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .buf = reset_on 1331215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D }, 13453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil }; 13553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil struct i2c_msg test[2] = { 1361215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D { 1371215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .addr = client->addr, 1381215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .len = 3, 1391215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .buf = write 1401215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D }, 1411215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D { 1421215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .addr = client->addr, 1431215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .flags = I2C_M_RD, 1441215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .len = 2, 1451215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .buf = read 1461215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D }, 14753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil }; 14853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 149f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(3, msp_debug, client, "msp_reset\n"); 15053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (i2c_transfer(client->adapter, &reset[0], 1) != 1 || 15153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil i2c_transfer(client->adapter, &reset[1], 1) != 1 || 15253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil i2c_transfer(client->adapter, test, 2) != 2) { 1537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_err(client, "chip reset failed\n"); 15453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return -1; 15553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 15653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 15753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 15853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 15953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int msp_read(struct i2c_client *client, int dev, int addr) 16053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 16153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil int err, retval; 16253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil u8 write[3]; 16353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil u8 read[2]; 16453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil struct i2c_msg msgs[2] = { 1651215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D { 1661215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .addr = client->addr, 1671215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .len = 3, 1681215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .buf = write 1691215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D }, 1701215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D { 1711215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .addr = client->addr, 1721215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .flags = I2C_M_RD, 1731215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .len = 2, 1741215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D .buf = read 1751215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D } 17653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil }; 17753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 17853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil write[0] = dev + 1; 17953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil write[1] = addr >> 8; 18053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil write[2] = addr & 0xff; 18153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 18253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil for (err = 0; err < 3; err++) { 18353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (i2c_transfer(client->adapter, msgs, 2) == 2) 18453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 1857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err, 18653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil dev, addr); 187f3a43d3082cd9c2308612e0331ad3b1b9d3a7a33Robert P. J. Day schedule_timeout_interruptible(msecs_to_jiffies(10)); 18853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 18953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (err == 3) { 190d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_warn(client, "resetting chip, sound will go off.\n"); 19153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_reset(client); 19253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return -1; 19353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 19453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil retval = read[0] << 8 | read[1]; 195d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(3, msp_debug, client, "msp_read(0x%x, 0x%x): 0x%x\n", 196d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil dev, addr, retval); 19753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return retval; 19853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 19953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 20053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_read_dem(struct i2c_client *client, int addr) 20153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 20253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return msp_read(client, I2C_MSP_DEM, addr); 20353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 20453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 20553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_read_dsp(struct i2c_client *client, int addr) 20653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 20753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return msp_read(client, I2C_MSP_DSP, addr); 20853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 20953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 21053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int msp_write(struct i2c_client *client, int dev, int addr, int val) 21153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 21253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil int err; 21353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil u8 buffer[5]; 21453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 21553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil buffer[0] = dev; 21653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil buffer[1] = addr >> 8; 21753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil buffer[2] = addr & 0xff; 21853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil buffer[3] = val >> 8; 21953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil buffer[4] = val & 0xff; 22053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 221d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(3, msp_debug, client, "msp_write(0x%x, 0x%x, 0x%x)\n", 222d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil dev, addr, val); 22353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil for (err = 0; err < 3; err++) { 22453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (i2c_master_send(client, buffer, 5) == 5) 22553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 2267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err, 22753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil dev, addr); 228f3a43d3082cd9c2308612e0331ad3b1b9d3a7a33Robert P. J. Day schedule_timeout_interruptible(msecs_to_jiffies(10)); 22953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 23053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (err == 3) { 231d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_warn(client, "resetting chip, sound will go off.\n"); 23253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_reset(client); 23353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return -1; 23453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 23553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 23653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 23753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 23853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_write_dem(struct i2c_client *client, int addr, int val) 23953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 24053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return msp_write(client, I2C_MSP_DEM, addr, val); 24153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 24253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 24353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_write_dsp(struct i2c_client *client, int addr, int val) 24453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 24553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return msp_write(client, I2C_MSP_DSP, addr, val); 24653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 24753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 24853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- * 24953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * bits 9 8 5 - SCART DSP input Select: 25053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 0 0 - SCART 1 to DSP input (reset position) 25153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 1 0 - MONO to DSP input 25253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 0 0 - SCART 2 to DSP input 25353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 1 1 - Mute DSP input 25453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 25553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * bits 11 10 6 - SCART 1 Output Select: 25653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 0 0 - undefined (reset position) 25753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS) 25853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 0 0 - MONO input to SCART 1 Output 25953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 1 0 - SCART 1 DA to SCART 1 Output 26053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 0 1 - SCART 2 DA to SCART 1 Output 26153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 1 1 - SCART 1 Input to SCART 1 Output 26253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 1 1 - Mute SCART 1 Output 26353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 26453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART): 26553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position) 26653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 1 0 - SCART 1 Input to SCART 2 Output 26753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 0 0 - MONO input to SCART 2 Output 26853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 0 1 - SCART 2 DA to SCART 2 Output 26953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 0 1 1 - SCART 2 Input to SCART 2 Output 27053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 1 1 0 - Mute SCART 2 Output 27153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 27253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Bits 4 to 0 should be zero. 27353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * ----------------------------------------------------------------------- */ 27453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 27553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int scarts[3][9] = { 276b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */ 27753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* SCART DSP Input select */ 278b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 }, 27953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* SCART1 Output select */ 280b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 }, 28153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* SCART2 Output select */ 282b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 }, 28353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}; 28453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 28553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic char *scart_names[] = { 286b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute" 28753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}; 28853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 28953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilvoid msp_set_scart(struct i2c_client *client, int in, int out) 29053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 29176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 29253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 293427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil state->in_scart = in; 29453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 295427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil if (in >= 0 && in <= 7 && out >= 0 && out <= 2) { 296427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil if (-1 == scarts[out][in + 1]) 29753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return; 29853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 299427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil state->acb &= ~scarts[out][0]; 300427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil state->acb |= scarts[out][in + 1]; 30153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } else 30253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->acb = 0xf60; /* Mute Input and SCART 1 Output */ 30353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 304f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "scart switch: %s => %d (ACB=0x%04x)\n", 305d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil scart_names[in], out, state->acb); 30653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_write_dsp(client, 0x13, state->acb); 30753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 30853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ 309dc555aa63c798af097f5c303bcf72a8390b03da5Hans Verkuil if (state->has_i2s_conf) 310dc555aa63c798af097f5c303bcf72a8390b03da5Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 31153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 31253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 31353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ------------------------------------------------------------------------ */ 31453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 31553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic void msp_wake_thread(struct i2c_client *client) 31653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 31776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 31853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 31953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (NULL == state->kthread) 32053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return; 32153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->watch_stereo = 0; 32253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->restart = 1; 32353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil wake_up_interruptible(&state->wq); 32453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 32553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 32653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_sleep(struct msp_state *state, int timeout) 32753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 32853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil DECLARE_WAITQUEUE(wait, current); 32953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 33053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil add_wait_queue(&state->wq, &wait); 33153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (!kthread_should_stop()) { 33253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (timeout < 0) { 33353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil set_current_state(TASK_INTERRUPTIBLE); 33453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil schedule(); 33553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } else { 33653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil schedule_timeout_interruptible 33753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil (msecs_to_jiffies(timeout)); 33853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 33953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 34053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 34153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil remove_wait_queue(&state->wq, &wait); 34253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil try_to_freeze(); 34353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return state->restart; 34453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 34553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 34653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ------------------------------------------------------------------------ */ 34753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 348ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuilstatic int msp_s_ctrl(struct v4l2_ctrl *ctrl) 34953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 350ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil struct msp_state *state = ctrl_to_state(ctrl); 351ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil struct i2c_client *client = v4l2_get_subdevdata(&state->sd); 352ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil int val = ctrl->val; 35353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 35453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil switch (ctrl->id) { 355ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil case V4L2_CID_AUDIO_VOLUME: { 356ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil /* audio volume cluster */ 357ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil int reallymuted = state->muted->val | state->scan_in_progress; 358ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 359ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (!reallymuted) 360ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil val = (val * 0x7f / 65535) << 8; 361ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 362ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n", 363ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil state->muted->val ? "on" : "off", 364ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil state->scan_in_progress ? "yes" : "no", 365ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil state->volume->val); 366ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 367ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0000, val); 368ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1)); 369ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_scart2_out_volume) 370ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1)); 371ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_headphones) 372ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0006, val); 37353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 37453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 37553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 37653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil case V4L2_CID_AUDIO_BASS: 377ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil val = ((val - 32768) * 0x60 / 65535) << 8; 378ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0002, val); 379ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_headphones) 380ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0031, val); 38153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 38253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 38353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil case V4L2_CID_AUDIO_TREBLE: 384ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil val = ((val - 32768) * 0x60 / 65535) << 8; 385ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0003, val); 386ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_headphones) 387ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0032, val); 38853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 38953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 390d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil case V4L2_CID_AUDIO_LOUDNESS: 391ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil val = val ? ((5 * 4) << 8) : 0; 392ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0004, val); 393ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_headphones) 394ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0033, val); 39553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 39653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 397d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil case V4L2_CID_AUDIO_BALANCE: 398ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil val = (u8)((val / 256) - 128); 399ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0001, val << 8); 400ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_headphones) 401ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_write_dsp(client, 0x0030, val << 8); 40253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 40353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 40453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil default: 40553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return -EINVAL; 40653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 40753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 40853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 40953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 410ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuilvoid msp_update_volume(struct msp_state *state) 411ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil{ 4120310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil /* Force an update of the volume/mute cluster */ 4130310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil v4l2_ctrl_lock(state->volume); 4140310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil state->volume->val = state->volume->cur.val; 4150310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil state->muted->val = state->muted->cur.val; 4160310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil msp_s_ctrl(state->volume); 4170310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil v4l2_ctrl_unlock(state->volume); 418ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil} 419ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 42076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil/* --- v4l2 ioctls --- */ 42176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_s_radio(struct v4l2_subdev *sd) 42276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 42376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 42476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 42553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 42676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (state->radio) 42753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 42876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->radio = 1; 42976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_dbg(1, msp_debug, client, "switching to radio mode\n"); 43076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->watch_stereo = 0; 43176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil switch (state->opmode) { 43276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil case OPMODE_MANUAL: 43376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil /* set msp3400 to FM radio mode */ 43476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_RADIO); 43576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(10.7), 43676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil MSP_CARRIER(10.7)); 437ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 43876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil break; 43976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil case OPMODE_AUTODETECT: 44076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil case OPMODE_AUTOSELECT: 44176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil /* the thread will do for us */ 44276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_wake_thread(client); 44376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil break; 44453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 44576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 44676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 44753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 448b530a447bb588fdf43fdf4eb909e4ee1921d47acHans Verkuilstatic int msp_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq) 44976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 45076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 45153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 45276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil /* new channel -- kick audio carrier scan */ 45376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_wake_thread(client); 45476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 45576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 4562474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 4575d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehabstatic int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id) 4585d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab{ 4595d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab struct msp_state *state = to_state(sd); 4605d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 4615d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 4625d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab *id &= state->detected_std; 4635d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 4645d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, 4655d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "detected standard: %s(0x%08Lx)\n", 4665d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab msp_standard_std_name(state->std), state->detected_std); 4675d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 4685d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab return 0; 4695d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab} 4705d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 47176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) 47276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 47376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 47476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 47576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil int update = state->radio || state->v4l2_std != id; 47676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 47776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->v4l2_std = id; 47876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->radio = 0; 47976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (update) 4802eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil msp_wake_thread(client); 48176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 48276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 48376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 4845325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic int msp_s_routing(struct v4l2_subdev *sd, 4855325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil u32 input, u32 output, u32 config) 48676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 48776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 48876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 4895325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil int tuner = (input >> 3) & 1; 4905325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil int sc_in = input & 0x7; 4915325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil int sc1_out = output & 0xf; 4925325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil int sc2_out = (output >> 4) & 0xf; 49376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil u16 val, reg; 49476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil int i; 49576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil int extern_input = 1; 49676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 4975325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil if (state->route_in == input && state->route_out == output) 49876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 4995325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil state->route_in = input; 5005325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil state->route_out = output; 50176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil /* check if the tuner input is used */ 50276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil for (i = 0; i < 5; i++) { 5035325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil if (((input >> (4 + i * 4)) & 0xf) == 0) 50476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil extern_input = 0; 50553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 50676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT; 50776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 50876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_set_scart(client, sc_in, 0); 50976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_set_scart(client, sc1_out, 1); 51076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_set_scart(client, sc2_out, 2); 51176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_set_audmode(client); 51276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; 51376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil val = msp_read_dem(client, reg); 51476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); 51576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil /* wake thread when a new input is chosen */ 51676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_wake_thread(client); 51776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 51876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 51953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 52076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) 52176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 52276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 52376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 52453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 525ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil if (vt->type != V4L2_TUNER_ANALOG_TV) 52676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 527ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil if (!state->radio) { 528ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil if (state->opmode == OPMODE_AUTOSELECT) 529ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil msp_detect_stereo(client); 530ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil vt->rxsubchans = state->rxsubchans; 531ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil } 532ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil vt->audmode = state->audmode; 53376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil vt->capability |= V4L2_TUNER_CAP_STEREO | 53476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; 53576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 53676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 53753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 5382f73c7c582a685b3198b974cd6d964d0338f8ab5Hans Verkuilstatic int msp_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) 53976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 54076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 54176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 54253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 54376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (state->radio) /* TODO: add mono/stereo support for radio */ 54476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 54576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (state->audmode == vt->audmode) 54676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 54776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil state->audmode = vt->audmode; 54876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil /* only set audmode */ 54976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_set_audmode(client); 55076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 55176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 55253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 55376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) 55476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 55576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 55676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 55753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 55876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", freq); 55953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 56076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil switch (freq) { 561d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil case 1024000: 562d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->i2s_mode = 0; 563d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil break; 564d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil case 2048000: 565d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->i2s_mode = 1; 566d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil break; 567d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil default: 568d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil return -EINVAL; 56953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 57076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil return 0; 57176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil} 57253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 57376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_log_status(struct v4l2_subdev *sd) 57476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{ 57576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(sd); 57676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 57776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil const char *p; 578ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil char prefix[V4L2_SUBDEV_NAME_SIZE + 20]; 57976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 58076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (state->opmode == OPMODE_AUTOSELECT) 58176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil msp_detect_stereo(client); 58276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", 58376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil client->name, state->rev1, state->rev2); 584ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil snprintf(prefix, sizeof(prefix), "%s: Audio: ", sd->name); 585ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_handler_log_status(&state->hdl, prefix); 58676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil switch (state->mode) { 5875af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; 5885af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_FM_RADIO: p = "FM Radio"; break; 58925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi case MSP_MODE_FM_TERRA: p = "Terrestrial FM-mono/stereo"; break; 5905af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break; 5915af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break; 5925af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break; 5935af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break; 5945af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_BTSC: p = "BTSC"; break; 5955af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil case MSP_MODE_EXTERN: p = "External input"; break; 5965af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil default: p = "unknown"; break; 59776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil } 59876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (state->mode == MSP_MODE_EXTERN) { 59976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "Mode: %s\n", p); 60076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil } else if (state->opmode == OPMODE_MANUAL) { 60176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "Mode: %s (%s%s)\n", p, 6025af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", 6035af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); 60476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil } else { 60576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil if (state->opmode == OPMODE_AUTODETECT) 60676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "Mode: %s\n", p); 60776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "Standard: %s (%s%s)\n", 6085af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(state->std), 6095af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", 6105af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); 61153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 61276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "Audmode: 0x%04x\n", state->audmode); 61376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n", 6145325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil state->route_in, state->route_out); 61576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l_info(client, "ACB: 0x%04x\n", state->acb); 61653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 61753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 61853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 6195cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown#ifdef CONFIG_PM_SLEEP 6205cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brownstatic int msp_suspend(struct device *dev) 62153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 6225cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown struct i2c_client *client = to_i2c_client(dev); 623f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "suspend\n"); 62453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_reset(client); 62553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 62653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 62753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 6285cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brownstatic int msp_resume(struct device *dev) 62953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 6305cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown struct i2c_client *client = to_i2c_client(dev); 631f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "resume\n"); 63253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_wake_thread(client); 63353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 63453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 6355cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown#endif 63653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 63776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil/* ----------------------------------------------------------------------- */ 63876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 639ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuilstatic const struct v4l2_ctrl_ops msp_ctrl_ops = { 640ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .s_ctrl = msp_s_ctrl, 641ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil}; 642ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 64376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_core_ops msp_core_ops = { 64476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .log_status = msp_log_status, 645ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, 646ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, 647ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, 648ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .g_ctrl = v4l2_subdev_g_ctrl, 649ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .s_ctrl = v4l2_subdev_s_ctrl, 650ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .queryctrl = v4l2_subdev_queryctrl, 651ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil .querymenu = v4l2_subdev_querymenu, 65276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}; 65376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 6545d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehabstatic const struct v4l2_subdev_video_ops msp_video_ops = { 6558774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart .s_std = msp_s_std, 6565d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab .querystd = msp_querystd, 6575d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab}; 6585d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 65976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_tuner_ops msp_tuner_ops = { 66076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .s_frequency = msp_s_frequency, 66176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .g_tuner = msp_g_tuner, 66276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .s_tuner = msp_s_tuner, 66376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .s_radio = msp_s_radio, 66476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}; 66576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 66676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_audio_ops msp_audio_ops = { 66776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .s_routing = msp_s_routing, 66876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .s_i2s_clock_freq = msp_s_i2s_clock_freq, 66976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}; 67076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 67176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_ops msp_ops = { 67276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .core = &msp_core_ops, 6735d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab .video = &msp_video_ops, 67476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .tuner = &msp_tuner_ops, 67576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil .audio = &msp_audio_ops, 67676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}; 67776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil 67853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- */ 67953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 680d2653e92732bd3911feff6bee5e23dbf959381dbJean Delvarestatic int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) 68153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 68253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil struct msp_state *state; 68376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct v4l2_subdev *sd; 684ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil struct v4l2_ctrl_handler *hdl; 68553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil int (*thread_func)(void *data) = NULL; 6867560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil int msp_hard; 6877560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil int msp_family; 6887560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil int msp_revision; 6897560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil int msp_product, msp_prod_hi, msp_prod_lo; 6907560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil int msp_rom; 69153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 692af294867a52bf718df835a688e8c786d550bee26Jean Delvare if (!id) 693af294867a52bf718df835a688e8c786d550bee26Jean Delvare strlcpy(client->name, "msp3400", sizeof(client->name)); 69453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 69553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (msp_reset(client) == -1) { 696f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); 697188f3457c21ac7869005021b56b4578293c644bbHans Verkuil return -ENODEV; 69853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 69953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 700c02b211df6fc54e51ee554c27a6736a11255a764Laurent Pinchart state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); 701d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (!state) 70253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return -ENOMEM; 703b2a657603e7285bf05b86ad198111b5403c57b41Mariusz Kozlowski 70476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil sd = &state->sd; 70576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l2_i2c_subdev_init(sd, client, &msp_ops); 70653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 7075af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->v4l2_std = V4L2_STD_NTSC; 7085d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_ALL; 7090020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil state->audmode = V4L2_TUNER_MODE_STEREO; 71053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->input = -1; 71153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->i2s_mode = 0; 71253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil init_waitqueue_head(&state->wq); 7132474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* These are the reset input/output positions */ 7145325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil state->route_in = MSP_INPUT_DEFAULT; 7155325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil state->route_out = MSP_OUTPUT_DEFAULT; 71653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 71753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->rev1 = msp_read_dsp(client, 0x1e); 71853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (state->rev1 != -1) 71953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->rev2 = msp_read_dsp(client, 0x1f); 720d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, "rev1=0x%04x, rev2=0x%04x\n", 721d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->rev1, state->rev2); 72253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) { 723d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 724d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "not an msp3400 (cannot read chip version)\n"); 725188f3457c21ac7869005021b56b4578293c644bbHans Verkuil return -ENODEV; 72653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 72753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 7287560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_family = ((state->rev1 >> 4) & 0x0f) + 3; 7297560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_product = (state->rev2 >> 8) & 0xff; 7307560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_prod_hi = msp_product / 10; 7317560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_prod_lo = msp_product % 10; 7327560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_revision = (state->rev1 & 0x0f) + '@'; 7337560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_hard = ((state->rev1 >> 8) & 0xff) + '@'; 7347560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil msp_rom = state->rev2 & 0x1f; 73574cab31c413c8615efe818d44ff4ac83e2a138beHans Verkuil /* Rev B=2, C=3, D=4, G=7 */ 736d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->ident = msp_family * 10000 + 4000 + msp_product * 10 + 737d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision - '@'; 7387560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil 7397560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* Has NICAM support: all mspx41x and mspx45x products have NICAM */ 740d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_nicam = 741d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_prod_hi == 1 || msp_prod_hi == 5; 7427560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* Has radio support: was added with revision G */ 743d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_radio = 744d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision >= 'G'; 7457560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* Has headphones output: not for stripped down products */ 746d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_headphones = 747d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_prod_lo < 5; 7480020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* Has scart2 input: not in stripped down products of the '3' family */ 749d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_scart2 = 750d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_family >= 4 || msp_prod_lo < 7; 7510020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* Has scart3 input: not in stripped down products of the '3' family */ 752d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_scart3 = 753d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_family >= 4 || msp_prod_lo < 5; 7547560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* Has scart4 input: not in pre D revisions, not in stripped D revs */ 755d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_scart4 = 756d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5); 757d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil /* Has scart2 output: not in stripped down products of 758d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * the '3' family */ 759d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_scart2_out = 760d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_family >= 4 || msp_prod_lo < 5; 761d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil /* Has scart2 a volume control? Not in pre-D revisions. */ 762d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_scart2_out_volume = 763d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision > 'C' && state->has_scart2_out; 7645af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil /* Has a configurable i2s out? */ 765d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_i2s_conf = 766d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision >= 'G' && msp_prod_lo < 7; 767d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil /* Has subwoofer output: not in pre-D revs and not in stripped down 768d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * products */ 769d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_subwoofer = 770d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision >= 'D' && msp_prod_lo < 5; 771d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil /* Has soundprocessing (bass/treble/balance/loudness/equalizer): 772d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * not in stripped down products */ 773d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_sound_processing = 774d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_prod_lo < 7; 7757560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* Has Virtual Dolby Surround: only in msp34x1 */ 776d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_virtual_dolby_surround = 777d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision == 'G' && msp_prod_lo == 1; 7787560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */ 779d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->has_dolby_pro_logic = 780d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_revision == 'G' && msp_prod_lo == 2; 781d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil /* The msp343xG supports BTSC only and cannot do Automatic Standard 782d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * Detection. */ 783d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->force_btsc = 784d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3; 78553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 78653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->opmode = opmode; 78753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (state->opmode == OPMODE_AUTO) { 78853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* MSP revision G and up have both autodetect and autoselect */ 7897560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (msp_revision >= 'G') 79053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->opmode = OPMODE_AUTOSELECT; 79153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* MSP revision D and up have autodetect */ 7927560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil else if (msp_revision >= 'D') 79353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->opmode = OPMODE_AUTODETECT; 79453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil else 79553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->opmode = OPMODE_MANUAL; 79653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 79753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 798ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil hdl = &state->hdl; 799ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_handler_init(hdl, 6); 800ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (state->has_sound_processing) { 801ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, 802ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil V4L2_CID_AUDIO_BASS, 0, 65535, 65535 / 100, 32768); 803ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, 804ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil V4L2_CID_AUDIO_TREBLE, 0, 65535, 65535 / 100, 32768); 805ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, 806ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 0); 807ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil } 808ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil state->volume = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, 809ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 58880); 810ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, 811ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768); 812ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil state->muted = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, 813ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); 814ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil sd->ctrl_handler = hdl; 815ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil if (hdl->error) { 816ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil int err = hdl->error; 817ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 818ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_handler_free(hdl); 819ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil return err; 820ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil } 821ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 822ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_cluster(2, &state->volume); 823ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_handler_setup(hdl); 824ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil 82553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* hello world :-) */ 826af294867a52bf718df835a688e8c786d550bee26Jean Delvare v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n", 827af294867a52bf718df835a688e8c786d550bee26Jean Delvare msp_family, msp_product, 828af294867a52bf718df835a688e8c786d550bee26Jean Delvare msp_revision, msp_hard, msp_rom, 829d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil client->addr << 1, client->adapter->name); 8307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_info(client, "%s ", client->name); 8317560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->has_nicam && state->has_radio) 832d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "supports nicam and radio, "); 8337560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil else if (state->has_nicam) 834d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "supports nicam, "); 8357560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil else if (state->has_radio) 836d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "supports radio, "); 837d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "mode is "); 83853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 83953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* version-specific initialization */ 84053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil switch (state->opmode) { 84153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil case OPMODE_MANUAL: 842d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "manual"); 84353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil thread_func = msp3400c_thread; 84453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 84553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil case OPMODE_AUTODETECT: 846d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "autodetect"); 84753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil thread_func = msp3410d_thread; 84853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 84953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil case OPMODE_AUTOSELECT: 850d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "autodetect and autoselect"); 85153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil thread_func = msp34xxg_thread; 85253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil break; 85353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 854d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil printk(KERN_CONT "\n"); 85553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 85653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* startup control thread if needed */ 85753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (thread_func) { 85853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->kthread = kthread_run(thread_func, client, "msp34xx"); 85953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 86025821400359d2b3daacfb93303944211b8411ac3Akinobu Mita if (IS_ERR(state->kthread)) 8617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil v4l_warn(client, "kernel_thread() failed\n"); 86253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_wake_thread(client); 86353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 86453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 86553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 86653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 86779518dafd59a812bb390f201c6f18a8f875fcffbHans Verkuilstatic int msp_remove(struct i2c_client *client) 86853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{ 86976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 87053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 87176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil v4l2_device_unregister_subdev(&state->sd); 87253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil /* shutdown control thread */ 87353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil if (state->kthread) { 87453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil state->restart = 1; 87553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil kthread_stop(state->kthread); 87653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil } 87753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil msp_reset(client); 87853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 879ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil v4l2_ctrl_handler_free(&state->hdl); 88053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil return 0; 88153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil} 88253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 88353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- */ 88453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 8855cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brownstatic const struct dev_pm_ops msp3400_pm_ops = { 8865cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown SET_SYSTEM_SLEEP_PM_OPS(msp_suspend, msp_resume) 8875cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown}; 8885cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown 889af294867a52bf718df835a688e8c786d550bee26Jean Delvarestatic const struct i2c_device_id msp_id[] = { 890af294867a52bf718df835a688e8c786d550bee26Jean Delvare { "msp3400", 0 }, 891af294867a52bf718df835a688e8c786d550bee26Jean Delvare { } 892af294867a52bf718df835a688e8c786d550bee26Jean Delvare}; 893af294867a52bf718df835a688e8c786d550bee26Jean DelvareMODULE_DEVICE_TABLE(i2c, msp_id); 894af294867a52bf718df835a688e8c786d550bee26Jean Delvare 89561a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuilstatic struct i2c_driver msp_driver = { 89661a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil .driver = { 89761a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil .owner = THIS_MODULE, 89861a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil .name = "msp3400", 8995cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown .pm = &msp3400_pm_ops, 90061a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil }, 90161a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil .probe = msp_probe, 90261a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil .remove = msp_remove, 90361a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil .id_table = msp_id, 90453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}; 90553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil 906c6e8d86fffd8edf1bfccbd441b1812ee919fe3d5Axel Linmodule_i2c_driver(msp_driver); 90761a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil 90853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* 90953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Overrides for Emacs so that we follow Linus's tabbing style. 91053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * --------------------------------------------------------------------------- 91153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Local variables: 91253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * c-basic-offset: 8 91353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * End: 91453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil */ 915