aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/msp3400.c111
1 files changed, 93 insertions, 18 deletions
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 4689dee882f3..117d124657d0 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -649,6 +649,30 @@ msp3400c_print_mode(struct msp3400c *msp)
649 } 649 }
650} 650}
651 651
652#define MSP3400_MAX 4
653static struct i2c_client *msps[MSP3400_MAX];
654static void msp3400c_restore_dfp(struct i2c_client *client)
655{
656 struct msp3400c *msp = i2c_get_clientdata(client);
657 int i;
658
659 for (i = 0; i < DFP_COUNT; i++) {
660 if (-1 == msp->dfp_regs[i])
661 continue;
662 msp3400c_write(client, I2C_MSP3400C_DFP, i, msp->dfp_regs[i]);
663 }
664}
665
666/* if the dfp_regs is set, set what's in there. Otherwise, set the default value */
667static int msp3400c_write_dfp_with_default(struct i2c_client *client,
668 int addr, int default_value)
669{
670 struct msp3400c *msp = i2c_get_clientdata(client);
671 int value = default_value;
672 if (addr < DFP_COUNT && -1 != msp->dfp_regs[addr])
673 value = msp->dfp_regs[addr];
674 return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value);
675}
652 676
653/* ----------------------------------------------------------------------- */ 677/* ----------------------------------------------------------------------- */
654 678
@@ -834,7 +858,8 @@ static int msp3400c_thread(void *data)
834 goto restart; 858 goto restart;
835 859
836 /* carrier detect pass #1 -- main carrier */ 860 /* carrier detect pass #1 -- main carrier */
837 cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main); 861 cd = carrier_detect_main;
862 count = CARRIER_COUNT(carrier_detect_main);
838 863
839 if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { 864 if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
840 /* autodetect doesn't work well with AM ... */ 865 /* autodetect doesn't work well with AM ... */
@@ -868,13 +893,16 @@ static int msp3400c_thread(void *data)
868 case 0: /* 4.5 */ 893 case 0: /* 4.5 */
869 case 2: /* 6.0 */ 894 case 2: /* 6.0 */
870 default: 895 default:
871 cd = NULL; count = 0; 896 cd = NULL;
897 count = 0;
872 break; 898 break;
873 } 899 }
874 900
875 if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { 901 if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
876 /* autodetect doesn't work well with AM ... */ 902 /* autodetect doesn't work well with AM ... */
877 cd = NULL; count = 0; max2 = 0; 903 cd = NULL;
904 count = 0;
905 max2 = 0;
878 } 906 }
879 for (this = 0; this < count; this++) { 907 for (this = 0; this < count; this++) {
880 msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); 908 msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
@@ -962,6 +990,8 @@ static int msp3400c_thread(void *data)
962 990
963 /* unmute */ 991 /* unmute */
964 msp3400c_setvolume(client, msp->muted, msp->left, msp->right); 992 msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
993 msp3400c_restore_dfp(client);
994
965 if (debug) 995 if (debug)
966 msp3400c_print_mode(msp); 996 msp3400c_print_mode(msp);
967 997
@@ -1207,6 +1237,7 @@ static int msp3410d_thread(void *data)
1207 msp3400c_settreble(client, msp->treble); 1237 msp3400c_settreble(client, msp->treble);
1208 msp3400c_setvolume(client, msp->muted, msp->left, msp->right); 1238 msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
1209 msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); 1239 msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb);
1240 msp3400c_restore_dfp(client);
1210 1241
1211 /* monitor tv audio mode */ 1242 /* monitor tv audio mode */
1212 while (msp->watch_stereo) { 1243 while (msp->watch_stereo) {
@@ -1230,7 +1261,7 @@ static void msp34xxg_set_source(struct i2c_client *client, int source);
1230/* (re-)initialize the msp34xxg, according to the current norm in msp->norm 1261/* (re-)initialize the msp34xxg, according to the current norm in msp->norm
1231 * return 0 if it worked, -1 if it failed 1262 * return 0 if it worked, -1 if it failed
1232 */ 1263 */
1233static int msp34xxg_init(struct i2c_client *client) 1264static int msp34xxg_reset(struct i2c_client *client)
1234{ 1265{
1235 struct msp3400c *msp = i2c_get_clientdata(client); 1266 struct msp3400c *msp = i2c_get_clientdata(client);
1236 int modus,std; 1267 int modus,std;
@@ -1257,7 +1288,7 @@ static int msp34xxg_init(struct i2c_client *client)
1257 return -1; 1288 return -1;
1258 if (msp3400c_write(client, 1289 if (msp3400c_write(client,
1259 I2C_MSP3400C_DEM, 1290 I2C_MSP3400C_DEM,
1260 0x20/*stanard*/, 1291 0x20/*standard*/,
1261 std)) 1292 std))
1262 return -1; 1293 return -1;
1263 1294
@@ -1265,21 +1296,18 @@ static int msp34xxg_init(struct i2c_client *client)
1265 standard/audio autodetection right now */ 1296 standard/audio autodetection right now */
1266 msp34xxg_set_source(client, msp->source); 1297 msp34xxg_set_source(client, msp->source);
1267 1298
1268 if (msp3400c_write(client, I2C_MSP3400C_DFP, 1299 if (msp3400c_write_dfp_with_default(client, 0x0e, /* AM/FM Prescale */
1269 0x0e, /* AM/FM Prescale */ 1300 0x3000
1270 0x3000 /* default: [15:8] 75khz deviation */)) 1301 /* default: [15:8] 75khz deviation */
1302 ))
1271 return -1; 1303 return -1;
1272 1304
1273 if (msp3400c_write(client, I2C_MSP3400C_DFP, 1305 if (msp3400c_write_dfp_with_default(client, 0x10, /* NICAM Prescale */
1274 0x10, /* NICAM Prescale */ 1306 0x5a00
1275 0x5a00 /* default: 9db gain (as recommended) */)) 1307 /* default: 9db gain (as recommended) */
1308 ))
1276 return -1; 1309 return -1;
1277 1310
1278 if (msp3400c_write(client,
1279 I2C_MSP3400C_DEM,
1280 0x20, /* STANDARD SELECT */
1281 standard /* default: 0x01 for automatic standard select*/))
1282 return -1;
1283 return 0; 1311 return 0;
1284} 1312}
1285 1313
@@ -1303,7 +1331,7 @@ static int msp34xxg_thread(void *data)
1303 break; 1331 break;
1304 1332
1305 /* setup the chip*/ 1333 /* setup the chip*/
1306 msp34xxg_init(client); 1334 msp34xxg_reset(client);
1307 std = standard; 1335 std = standard;
1308 if (std != 0x01) 1336 if (std != 0x01)
1309 goto unmute; 1337 goto unmute;
@@ -1486,6 +1514,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
1486 struct msp3400c *msp; 1514 struct msp3400c *msp;
1487 struct i2c_client *c; 1515 struct i2c_client *c;
1488 int (*thread_func)(void *data) = NULL; 1516 int (*thread_func)(void *data) = NULL;
1517 int i;
1489 1518
1490 client_template.adapter = adap; 1519 client_template.adapter = adap;
1491 client_template.addr = addr; 1520 client_template.addr = addr;
@@ -1504,12 +1533,15 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
1504 } 1533 }
1505 1534
1506 memset(msp,0,sizeof(struct msp3400c)); 1535 memset(msp,0,sizeof(struct msp3400c));
1536 msp->norm = VIDEO_MODE_NTSC;
1507 msp->left = 58880; /* 0db gain */ 1537 msp->left = 58880; /* 0db gain */
1508 msp->right = 58880; /* 0db gain */ 1538 msp->right = 58880; /* 0db gain */
1509 msp->bass = 32768; 1539 msp->bass = 32768;
1510 msp->treble = 32768; 1540 msp->treble = 32768;
1511 msp->input = -1; 1541 msp->input = -1;
1512 msp->muted = 0; 1542 msp->muted = 0;
1543 for (i = 0; i < DFP_COUNT; i++)
1544 msp->dfp_regs[i] = -1;
1513 1545
1514 i2c_set_clientdata(c, msp); 1546 i2c_set_clientdata(c, msp);
1515 init_waitqueue_head(&msp->wq); 1547 init_waitqueue_head(&msp->wq);
@@ -1579,6 +1611,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
1579 /* startup control thread if needed */ 1611 /* startup control thread if needed */
1580 if (thread_func) { 1612 if (thread_func) {
1581 msp->kthread = kthread_run(thread_func, c, "msp34xx"); 1613 msp->kthread = kthread_run(thread_func, c, "msp34xx");
1614
1582 if (NULL == msp->kthread) 1615 if (NULL == msp->kthread)
1583 printk(KERN_WARNING "msp34xx: kernel_thread() failed\n"); 1616 printk(KERN_WARNING "msp34xx: kernel_thread() failed\n");
1584 msp_wake_thread(c); 1617 msp_wake_thread(c);
@@ -1587,21 +1620,39 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
1587 /* done */ 1620 /* done */
1588 i2c_attach_client(c); 1621 i2c_attach_client(c);
1589 1622
1623 /* update our own array */
1624 for (i = 0; i < MSP3400_MAX; i++) {
1625 if (NULL == msps[i]) {
1626 msps[i] = c;
1627 break;
1628 }
1629 }
1630
1590 return 0; 1631 return 0;
1591} 1632}
1592 1633
1593static int msp_detach(struct i2c_client *client) 1634static int msp_detach(struct i2c_client *client)
1594{ 1635{
1595 struct msp3400c *msp = i2c_get_clientdata(client); 1636 struct msp3400c *msp = i2c_get_clientdata(client);
1637 int i;
1596 1638
1597 /* shutdown control thread */ 1639 /* shutdown control thread */
1598 if (msp->kthread) { 1640 if (msp->kthread) {
1599 msp->restart = 1; 1641 msp->restart = 1;
1600 kthread_stop(msp->kthread); 1642 kthread_stop(msp->kthread);
1601 } 1643 }
1602 msp3400c_reset(client); 1644 msp3400c_reset(client);
1645
1646 /* update our own array */
1647 for (i = 0; i < MSP3400_MAX; i++) {
1648 if (client == msps[i]) {
1649 msps[i] = NULL;
1650 break;
1651 }
1652 }
1603 1653
1604 i2c_detach_client(client); 1654 i2c_detach_client(client);
1655
1605 kfree(msp); 1656 kfree(msp);
1606 kfree(client); 1657 kfree(client);
1607 return 0; 1658 return 0;
@@ -1753,6 +1804,30 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
1753 break; 1804 break;
1754 } 1805 }
1755 break; 1806 break;
1807 /* work-in-progress: hook to control the DFP registers */
1808 case MSP_SET_DFPREG:
1809 {
1810 struct msp_dfpreg *r = arg;
1811 int i;
1812
1813 if (r->reg < 0 || r->reg >= DFP_COUNT)
1814 return -EINVAL;
1815 for (i = 0; i < sizeof(bl_dfp) / sizeof(int); i++)
1816 if (r->reg == bl_dfp[i])
1817 return -EINVAL;
1818 msp->dfp_regs[r->reg] = r->value;
1819 msp3400c_write(client, I2C_MSP3400C_DFP, r->reg, r->value);
1820 return 0;
1821 }
1822 case MSP_GET_DFPREG:
1823 {
1824 struct msp_dfpreg *r = arg;
1825
1826 if (r->reg < 0 || r->reg >= DFP_COUNT)
1827 return -EINVAL;
1828 r->value = msp3400c_read(client, I2C_MSP3400C_DFP, r->reg);
1829 return 0;
1830 }
1756 1831
1757 /* --- v4l ioctls --- */ 1832 /* --- v4l ioctls --- */
1758 /* take care: bttv does userspace copying, we'll get a 1833 /* take care: bttv does userspace copying, we'll get a