Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] em28xx: add support for PLEX PX-BCUD (ISDB-S)

PX-BCUD has the following components:
USB interface: Empia EM28178
Demodulator: Toshiba TC90532 (works by code for TC90522)
Tuner: Next version of Sharp QM1D1C0042

em28xx_dvb_init(): add init code for PLEX PX-BCUD with calling
px_bcud_init() that does things like pin configuration.

qm1d1c0042_init(): support the next version of QM1D1C0042, change to
choose an appropriate array of initial registers by reading chip id.

[mchehab@osg.samsung.com: fold a fixup patch and fix checkpatch.pl
errors/warnings, where applicable]
Signed-off-by: Satoshi Nagahama <sattnag@aim.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Satoshi Nagahama and committed by
Mauro Carvalho Chehab
ab4d1452 7977a15e

+180 -10
+26 -10
drivers/media/tuners/qm1d1c0042.c
··· 32 32 #include "qm1d1c0042.h" 33 33 34 34 #define QM1D1C0042_NUM_REGS 0x20 35 + #define QM1D1C0042_NUM_REG_ROWS 2 35 36 36 - static const u8 reg_initval[QM1D1C0042_NUM_REGS] = { 37 - 0x48, 0x1c, 0xa0, 0x10, 0xbc, 0xc5, 0x20, 0x33, 38 - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 39 - 0x00, 0xff, 0xf3, 0x00, 0x2a, 0x64, 0xa6, 0x86, 40 - 0x8c, 0xcf, 0xb8, 0xf1, 0xa8, 0xf2, 0x89, 0x00 37 + static const u8 38 + reg_initval[QM1D1C0042_NUM_REG_ROWS][QM1D1C0042_NUM_REGS] = { { 39 + 0x48, 0x1c, 0xa0, 0x10, 0xbc, 0xc5, 0x20, 0x33, 40 + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 41 + 0x00, 0xff, 0xf3, 0x00, 0x2a, 0x64, 0xa6, 0x86, 42 + 0x8c, 0xcf, 0xb8, 0xf1, 0xa8, 0xf2, 0x89, 0x00 43 + }, { 44 + 0x68, 0x1c, 0xc0, 0x10, 0xbc, 0xc1, 0x11, 0x33, 45 + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 46 + 0x00, 0xff, 0xf3, 0x00, 0x3f, 0x25, 0x5c, 0xd6, 47 + 0x55, 0xcf, 0x95, 0xf6, 0x36, 0xf2, 0x09, 0x00 48 + } 41 49 }; 50 + 51 + static int reg_index; 42 52 43 53 static const struct qm1d1c0042_config default_cfg = { 44 54 .xtal_freq = 16000, ··· 330 320 int i, ret; 331 321 332 322 state = fe->tuner_priv; 333 - memcpy(state->regs, reg_initval, sizeof(reg_initval)); 334 323 335 324 reg_write(state, 0x01, 0x0c); 336 325 reg_write(state, 0x01, 0x0c); ··· 339 330 goto failed; 340 331 usleep_range(2000, 3000); 341 332 342 - val = state->regs[0x01] | 0x10; 343 - ret = reg_write(state, 0x01, val); /* soft reset off */ 333 + ret = reg_write(state, 0x01, 0x1c); /* soft reset off */ 344 334 if (ret < 0) 345 335 goto failed; 346 336 347 - /* check ID */ 337 + /* check ID and choose initial registers corresponding ID */ 348 338 ret = reg_read(state, 0x00, &val); 349 - if (ret < 0 || val != 0x48) 339 + if (ret < 0) 350 340 goto failed; 341 + for (reg_index = 0; reg_index < QM1D1C0042_NUM_REG_ROWS; 342 + reg_index++) { 343 + if (val == reg_initval[reg_index][0x00]) 344 + break; 345 + } 346 + if (reg_index >= QM1D1C0042_NUM_REG_ROWS) 347 + goto failed; 348 + memcpy(state->regs, reg_initval[reg_index], QM1D1C0042_NUM_REGS); 351 349 usleep_range(2000, 3000); 352 350 353 351 state->regs[0x0c] |= 0x40;
+2
drivers/media/usb/em28xx/Kconfig
··· 59 59 select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT 60 60 select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT 61 61 select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT 62 + select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT 63 + select MEDIA_TUNER_QM1D1C0042 if MEDIA_SUBDRV_AUTOSELECT 62 64 ---help--- 63 65 This adds support for DVB cards based on the 64 66 Empiatech em28xx chips.
+30
drivers/media/usb/em28xx/em28xx-cards.c
··· 492 492 {-1, -1, -1, -1}, 493 493 }; 494 494 495 + static struct em28xx_reg_seq plex_px_bcud[] = { 496 + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0}, 497 + {0x0d, 0xff, 0xff, 0}, 498 + {EM2874_R50_IR_CONFIG, 0x01, 0xff, 0}, 499 + {EM28XX_R06_I2C_CLK, 0x40, 0xff, 0}, 500 + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 100}, 501 + {EM28XX_R12_VINENABLE, 0x20, 0x20, 0}, 502 + {0x0d, 0x42, 0xff, 1000}, 503 + {EM2874_R80_GPIO_P0_CTRL, 0xfc, 0xff, 10}, 504 + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10}, 505 + {0x73, 0xfd, 0xff, 100}, 506 + {-1, -1, -1, -1}, 507 + }; 508 + 495 509 /* 496 510 * Button definitions 497 511 */ ··· 2320 2306 .has_dvb = 1, 2321 2307 .ir_codes = RC_MAP_TERRATEC_SLIM_2, 2322 2308 }, 2309 + 2310 + /* 2311 + * 3275:0085 PLEX PX-BCUD. 2312 + * Empia EM28178, TOSHIBA TC90532XBG, Sharp QM1D1C0042 2313 + */ 2314 + [EM28178_BOARD_PLEX_PX_BCUD] = { 2315 + .name = "PLEX PX-BCUD", 2316 + .xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ, 2317 + .def_i2c_bus = 1, 2318 + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, 2319 + .tuner_type = TUNER_ABSENT, 2320 + .tuner_gpio = plex_px_bcud, 2321 + .has_dvb = 1, 2322 + }, 2323 2323 }; 2324 2324 EXPORT_SYMBOL_GPL(em28xx_boards); 2325 2325 ··· 2523 2495 .driver_info = EM2861_BOARD_LEADTEK_VC100 }, 2524 2496 { USB_DEVICE(0xeb1a, 0x8179), 2525 2497 .driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD }, 2498 + { USB_DEVICE(0x3275, 0x0085), 2499 + .driver_info = EM28178_BOARD_PLEX_PX_BCUD }, 2526 2500 { }, 2527 2501 }; 2528 2502 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
+121
drivers/media/usb/em28xx/em28xx-dvb.c
··· 58 58 #include "ts2020.h" 59 59 #include "si2168.h" 60 60 #include "si2157.h" 61 + #include "tc90522.h" 62 + #include "qm1d1c0042.h" 61 63 62 64 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 63 65 MODULE_LICENSE("GPL"); ··· 788 786 mt352_write(fe, tuner_go, sizeof(tuner_go)); 789 787 return 0; 790 788 } 789 + 790 + static void px_bcud_init(struct em28xx *dev) 791 + { 792 + int i; 793 + struct { 794 + unsigned char r[4]; 795 + int len; 796 + } regs1[] = { 797 + {{ 0x0e, 0x77 }, 2}, 798 + {{ 0x0f, 0x77 }, 2}, 799 + {{ 0x03, 0x90 }, 2}, 800 + }, regs2[] = { 801 + {{ 0x07, 0x01 }, 2}, 802 + {{ 0x08, 0x10 }, 2}, 803 + {{ 0x13, 0x00 }, 2}, 804 + {{ 0x17, 0x00 }, 2}, 805 + {{ 0x03, 0x01 }, 2}, 806 + {{ 0x10, 0xb1 }, 2}, 807 + {{ 0x11, 0x40 }, 2}, 808 + {{ 0x85, 0x7a }, 2}, 809 + {{ 0x87, 0x04 }, 2}, 810 + }; 811 + static struct em28xx_reg_seq gpio[] = { 812 + {EM28XX_R06_I2C_CLK, 0x40, 0xff, 300}, 813 + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 60}, 814 + {EM28XX_R15_RGAIN, 0x20, 0xff, 0}, 815 + {EM28XX_R16_GGAIN, 0x20, 0xff, 0}, 816 + {EM28XX_R17_BGAIN, 0x20, 0xff, 0}, 817 + {EM28XX_R18_ROFFSET, 0x00, 0xff, 0}, 818 + {EM28XX_R19_GOFFSET, 0x00, 0xff, 0}, 819 + {EM28XX_R1A_BOFFSET, 0x00, 0xff, 0}, 820 + {EM28XX_R23_UOFFSET, 0x00, 0xff, 0}, 821 + {EM28XX_R24_VOFFSET, 0x00, 0xff, 0}, 822 + {EM28XX_R26_COMPR, 0x00, 0xff, 0}, 823 + {0x13, 0x08, 0xff, 0}, 824 + {EM28XX_R12_VINENABLE, 0x27, 0xff, 0}, 825 + {EM28XX_R0C_USBSUSP, 0x10, 0xff, 0}, 826 + {EM28XX_R27_OUTFMT, 0x00, 0xff, 0}, 827 + {EM28XX_R10_VINMODE, 0x00, 0xff, 0}, 828 + {EM28XX_R11_VINCTRL, 0x11, 0xff, 0}, 829 + {EM2874_R50_IR_CONFIG, 0x01, 0xff, 0}, 830 + {EM2874_R5F_TS_ENABLE, 0x80, 0xff, 0}, 831 + {EM28XX_R06_I2C_CLK, 0x46, 0xff, 0}, 832 + }; 833 + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x46); 834 + /* sleeping ISDB-T */ 835 + dev->dvb->i2c_client_demod->addr = 0x14; 836 + for (i = 0; i < ARRAY_SIZE(regs1); i++) 837 + i2c_master_send(dev->dvb->i2c_client_demod, regs1[i].r, 838 + regs1[i].len); 839 + /* sleeping ISDB-S */ 840 + dev->dvb->i2c_client_demod->addr = 0x15; 841 + for (i = 0; i < ARRAY_SIZE(regs2); i++) 842 + i2c_master_send(dev->dvb->i2c_client_demod, regs2[i].r, 843 + regs2[i].len); 844 + for (i = 0; i < ARRAY_SIZE(gpio); i++) { 845 + em28xx_write_reg_bits(dev, gpio[i].reg, gpio[i].val, 846 + gpio[i].mask); 847 + if (gpio[i].sleep > 0) 848 + msleep(gpio[i].sleep); 849 + } 850 + }; 791 851 792 852 static struct mt352_config terratec_xs_mt352_cfg = { 793 853 .demod_address = (0x1e >> 1), ··· 1824 1760 } 1825 1761 1826 1762 dvb->i2c_client_tuner = client; 1763 + } 1764 + break; 1765 + 1766 + case EM28178_BOARD_PLEX_PX_BCUD: 1767 + { 1768 + struct i2c_client *client; 1769 + struct i2c_board_info info; 1770 + struct tc90522_config tc90522_config; 1771 + struct qm1d1c0042_config qm1d1c0042_config; 1772 + 1773 + /* attach demod */ 1774 + memset(&tc90522_config, 0, sizeof(tc90522_config)); 1775 + memset(&info, 0, sizeof(struct i2c_board_info)); 1776 + strlcpy(info.type, "tc90522sat", I2C_NAME_SIZE); 1777 + info.addr = 0x15; 1778 + info.platform_data = &tc90522_config; 1779 + request_module("tc90522"); 1780 + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); 1781 + if (client == NULL || client->dev.driver == NULL) { 1782 + result = -ENODEV; 1783 + goto out_free; 1784 + } 1785 + dvb->i2c_client_demod = client; 1786 + if (!try_module_get(client->dev.driver->owner)) { 1787 + i2c_unregister_device(client); 1788 + result = -ENODEV; 1789 + goto out_free; 1790 + } 1791 + 1792 + /* attach tuner */ 1793 + memset(&qm1d1c0042_config, 0, 1794 + sizeof(qm1d1c0042_config)); 1795 + qm1d1c0042_config.fe = tc90522_config.fe; 1796 + qm1d1c0042_config.lpf = 1; 1797 + memset(&info, 0, sizeof(struct i2c_board_info)); 1798 + strlcpy(info.type, "qm1d1c0042", I2C_NAME_SIZE); 1799 + info.addr = 0x61; 1800 + info.platform_data = &qm1d1c0042_config; 1801 + request_module(info.type); 1802 + client = i2c_new_device(tc90522_config.tuner_i2c, 1803 + &info); 1804 + if (client == NULL || client->dev.driver == NULL) { 1805 + module_put(dvb->i2c_client_demod->dev.driver->owner); 1806 + i2c_unregister_device(dvb->i2c_client_demod); 1807 + result = -ENODEV; 1808 + goto out_free; 1809 + } 1810 + dvb->i2c_client_tuner = client; 1811 + if (!try_module_get(client->dev.driver->owner)) { 1812 + i2c_unregister_device(client); 1813 + module_put(dvb->i2c_client_demod->dev.driver->owner); 1814 + i2c_unregister_device(dvb->i2c_client_demod); 1815 + result = -ENODEV; 1816 + goto out_free; 1817 + } 1818 + dvb->fe[0] = tc90522_config.fe; 1819 + px_bcud_init(dev); 1827 1820 } 1828 1821 break; 1829 1822 default:
+1
drivers/media/usb/em28xx/em28xx.h
··· 145 145 #define EM2861_BOARD_LEADTEK_VC100 95 146 146 #define EM28178_BOARD_TERRATEC_T2_STICK_HD 96 147 147 #define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 97 148 + #define EM28178_BOARD_PLEX_PX_BCUD 98 148 149 149 150 /* Limits minimum and default number of buffers */ 150 151 #define EM28XX_MIN_BUF 4