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

[media] Add support for KWorld PC150-U ATSC hybrid tuner card

[mchehab@redhat.com: CodingStyle fixes]
Signed-off-by: Kyle Strickland <kyle@kyle.strickland.name>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Kyle Strickland and committed by
Mauro Carvalho Chehab
25fa2071 8d834b52

+287 -3
+1
Documentation/dvb/cards.txt
··· 119 119 - Compro Videomate DVB-T300 120 120 - Compro Videomate DVB-T200 121 121 - AVerMedia AVerTVHD MCE A180 122 + - KWorld PC150-U ATSC Hybrid 122 123
+1
drivers/media/rc/keymaps/Makefile
··· 45 45 rc-it913x-v2.o \ 46 46 rc-kaiomy.o \ 47 47 rc-kworld-315u.o \ 48 + rc-kworld-pc150u.o \ 48 49 rc-kworld-plus-tv-analog.o \ 49 50 rc-leadtek-y04g0051.o \ 50 51 rc-lirc.o \
+102
drivers/media/rc/keymaps/rc-kworld-pc150u.c
··· 1 + /* kworld-pc150u.c - Keytable for kworld_pc150u Remote Controller 2 + * 3 + * keymap imported from ir-keymaps.c 4 + * 5 + * Copyright (c) 2010 by Kyle Strickland 6 + * (based on kworld-plus-tv-analog.c by 7 + * Mauro Carvalho Chehab <mchehab@redhat.com>) 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + */ 14 + 15 + #include <media/rc-map.h> 16 + #include <linux/module.h> 17 + 18 + /* Kworld PC150-U 19 + Kyle Strickland <kyle@kyle.strickland.name> 20 + */ 21 + 22 + static struct rc_map_table kworld_pc150u[] = { 23 + { 0x0c, KEY_MEDIA }, /* Kworld key */ 24 + { 0x16, KEY_EJECTCLOSECD }, /* -> ) */ 25 + { 0x1d, KEY_POWER2 }, 26 + 27 + { 0x00, KEY_1 }, 28 + { 0x01, KEY_2 }, 29 + { 0x02, KEY_3 }, 30 + { 0x03, KEY_4 }, 31 + { 0x04, KEY_5 }, 32 + { 0x05, KEY_6 }, 33 + { 0x06, KEY_7 }, 34 + { 0x07, KEY_8 }, 35 + { 0x08, KEY_9 }, 36 + { 0x0a, KEY_0 }, 37 + 38 + { 0x09, KEY_AGAIN }, 39 + { 0x14, KEY_MUTE }, 40 + 41 + { 0x1e, KEY_LAST }, 42 + { 0x17, KEY_ZOOM }, 43 + { 0x1f, KEY_HOMEPAGE }, 44 + { 0x0e, KEY_ESC }, 45 + 46 + { 0x20, KEY_UP }, 47 + { 0x21, KEY_DOWN }, 48 + { 0x42, KEY_LEFT }, 49 + { 0x43, KEY_RIGHT }, 50 + { 0x0b, KEY_ENTER }, 51 + 52 + { 0x10, KEY_CHANNELUP }, 53 + { 0x11, KEY_CHANNELDOWN }, 54 + 55 + { 0x13, KEY_VOLUMEUP }, 56 + { 0x12, KEY_VOLUMEDOWN }, 57 + 58 + { 0x19, KEY_TIME}, /* Timeshift */ 59 + { 0x1a, KEY_STOP}, 60 + { 0x1b, KEY_RECORD}, 61 + { 0x4b, KEY_EMAIL}, 62 + 63 + { 0x40, KEY_REWIND}, 64 + { 0x44, KEY_PLAYPAUSE}, 65 + { 0x41, KEY_FORWARD}, 66 + { 0x22, KEY_TEXT}, 67 + 68 + { 0x15, KEY_AUDIO}, /* ((*)) */ 69 + { 0x0f, KEY_MODE}, /* display ratio */ 70 + { 0x1c, KEY_SYSRQ}, /* snapshot */ 71 + { 0x4a, KEY_SLEEP}, /* sleep timer */ 72 + 73 + { 0x48, KEY_SOUND}, /* switch theater mode */ 74 + { 0x49, KEY_BLUE}, /* A */ 75 + { 0x18, KEY_RED}, /* B */ 76 + { 0x23, KEY_GREEN}, /* C */ 77 + }; 78 + 79 + static struct rc_map_list kworld_pc150u_map = { 80 + .map = { 81 + .scan = kworld_pc150u, 82 + .size = ARRAY_SIZE(kworld_pc150u), 83 + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ 84 + .name = RC_MAP_KWORLD_PC150U, 85 + } 86 + }; 87 + 88 + static int __init init_rc_map_kworld_pc150u(void) 89 + { 90 + return rc_map_register(&kworld_pc150u_map); 91 + } 92 + 93 + static void __exit exit_rc_map_kworld_pc150u(void) 94 + { 95 + rc_map_unregister(&kworld_pc150u_map); 96 + } 97 + 98 + module_init(init_rc_map_kworld_pc150u) 99 + module_exit(exit_rc_map_kworld_pc150u) 100 + 101 + MODULE_LICENSE("GPL"); 102 + MODULE_AUTHOR("Kyle Strickland <kyle@kyle.strickland.name>");
+59
drivers/media/video/saa7134/saa7134-cards.c
··· 33 33 #include "tea5767.h" 34 34 #include "tda18271.h" 35 35 #include "xc5000.h" 36 + #include "s5h1411.h" 36 37 37 38 /* commly used strings */ 38 39 static char name_mute[] = "mute"; ··· 5713 5712 .amux = LINE1, 5714 5713 } }, 5715 5714 }, 5715 + [SAA7134_BOARD_KWORLD_PC150U] = { 5716 + .name = "Kworld PC150-U", 5717 + .audio_clock = 0x00187de7, 5718 + .tuner_type = TUNER_PHILIPS_TDA8290, 5719 + .radio_type = UNSET, 5720 + .tuner_addr = ADDR_UNSET, 5721 + .radio_addr = ADDR_UNSET, 5722 + .mpeg = SAA7134_MPEG_DVB, 5723 + .gpiomask = 1 << 21, 5724 + .ts_type = SAA7134_MPEG_TS_PARALLEL, 5725 + .inputs = { { 5726 + .name = name_tv, 5727 + .vmux = 1, 5728 + .amux = TV, 5729 + .tv = 1, 5730 + }, { 5731 + .name = name_comp, 5732 + .vmux = 3, 5733 + .amux = LINE1, 5734 + }, { 5735 + .name = name_svideo, 5736 + .vmux = 8, 5737 + .amux = LINE2, 5738 + } }, 5739 + .radio = { 5740 + .name = name_radio, 5741 + .amux = TV, 5742 + .gpio = 0x0000000, 5743 + }, 5744 + }, 5716 5745 5717 5746 }; 5718 5747 ··· 6336 6305 .subdevice = 0x7352, 6337 6306 .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ 6338 6307 },{ 6308 + .vendor = PCI_VENDOR_ID_PHILIPS, 6309 + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ 6310 + .subvendor = 0x17de, 6311 + .subdevice = 0xa134, 6312 + .driver_data = SAA7134_BOARD_KWORLD_PC150U, 6313 + }, { 6339 6314 .vendor = PCI_VENDOR_ID_PHILIPS, 6340 6315 .device = PCI_DEVICE_ID_PHILIPS_SAA7134, 6341 6316 .subvendor = 0x1461, ··· 7171 7134 return 0; 7172 7135 } 7173 7136 7137 + static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev, 7138 + enum tda18271_mode mode) 7139 + { 7140 + switch (mode) { 7141 + case TDA18271_ANALOG: 7142 + saa7134_set_gpio(dev, 18, 0); 7143 + break; 7144 + case TDA18271_DIGITAL: 7145 + saa7134_set_gpio(dev, 18, 1); 7146 + msleep(30); 7147 + break; 7148 + default: 7149 + return -EINVAL; 7150 + } 7151 + return 0; 7152 + } 7153 + 7174 7154 static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, 7175 7155 int command, int arg) 7176 7156 { ··· 7203 7149 break; 7204 7150 case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: 7205 7151 ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); 7152 + break; 7153 + case SAA7134_BOARD_KWORLD_PC150U: 7154 + ret = saa7134_kworld_pc150u_toggle_agc(dev, arg); 7206 7155 break; 7207 7156 default: 7208 7157 break; ··· 7228 7171 case SAA7134_BOARD_HAUPPAUGE_HVR1120: 7229 7172 case SAA7134_BOARD_AVERMEDIA_M733A: 7230 7173 case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: 7174 + case SAA7134_BOARD_KWORLD_PC150U: 7231 7175 case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: 7232 7176 /* tda8290 + tda18271 */ 7233 7177 ret = saa7134_tda8290_18271_callback(dev, command, arg); ··· 7510 7452 case SAA7134_BOARD_BEHOLD_X7: 7511 7453 case SAA7134_BOARD_BEHOLD_H7: 7512 7454 case SAA7134_BOARD_BEHOLD_A7: 7455 + case SAA7134_BOARD_KWORLD_PC150U: 7513 7456 dev->has_remote = SAA7134_REMOTE_I2C; 7514 7457 break; 7515 7458 case SAA7134_BOARD_AVERMEDIA_A169_B:
+44
drivers/media/video/saa7134/saa7134-dvb.c
··· 61 61 #include "zl10036.h" 62 62 #include "zl10039.h" 63 63 #include "mt312.h" 64 + #include "s5h1411.h" 64 65 65 66 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); 66 67 MODULE_LICENSE("GPL"); ··· 1159 1158 .output_opt = TDA18271_OUTPUT_LT_OFF, 1160 1159 }; 1161 1160 1161 + static struct tda18271_std_map kworld_tda18271_std_map = { 1162 + .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 3, 1163 + .if_lvl = 6, .rfagc_top = 0x37 }, 1164 + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, 1165 + .if_lvl = 6, .rfagc_top = 0x37 }, 1166 + }; 1167 + 1168 + static struct tda18271_config kworld_pc150u_tda18271_config = { 1169 + .std_map = &kworld_tda18271_std_map, 1170 + .gate = TDA18271_GATE_ANALOG, 1171 + .output_opt = TDA18271_OUTPUT_LT_OFF, 1172 + .config = 3, /* Use tuner callback for AGC */ 1173 + .rf_cal_on_startup = 1 1174 + }; 1175 + 1176 + static struct s5h1411_config kworld_s5h1411_config = { 1177 + .output_mode = S5H1411_PARALLEL_OUTPUT, 1178 + .gpio = S5H1411_GPIO_OFF, 1179 + .qam_if = S5H1411_IF_4000, 1180 + .vsb_if = S5H1411_IF_3250, 1181 + .inversion = S5H1411_INVERSION_ON, 1182 + .status_mode = S5H1411_DEMODLOCKING, 1183 + .mpeg_timing = 1184 + S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, 1185 + }; 1186 + 1187 + 1162 1188 /* ================================================================== 1163 1189 * Core code 1164 1190 */ ··· 1465 1437 dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 1466 1438 &dev->i2c_adap, 0x61, 1467 1439 TUNER_PHILIPS_TUV1236D); 1440 + break; 1441 + case SAA7134_BOARD_KWORLD_PC150U: 1442 + saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */ 1443 + saa7134_tuner_callback(dev, 0, 1444 + TDA18271_CALLBACK_CMD_AGC_ENABLE, 1); 1445 + fe0->dvb.frontend = dvb_attach(s5h1411_attach, 1446 + &kworld_s5h1411_config, 1447 + &dev->i2c_adap); 1448 + if (fe0->dvb.frontend != NULL) { 1449 + dvb_attach(tda829x_attach, fe0->dvb.frontend, 1450 + &dev->i2c_adap, 0x4b, 1451 + &tda829x_no_probe); 1452 + dvb_attach(tda18271_attach, fe0->dvb.frontend, 1453 + 0x60, &dev->i2c_adap, 1454 + &kworld_pc150u_tda18271_config); 1455 + } 1468 1456 break; 1469 1457 case SAA7134_BOARD_FLYDVBS_LR300: 1470 1458 fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+13 -1
drivers/media/video/saa7134/saa7134-i2c.c
··· 254 254 addr = msgs[i].addr << 1; 255 255 if (msgs[i].flags & I2C_M_RD) 256 256 addr |= 1; 257 - if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { 257 + if (i > 0 && msgs[i].flags & 258 + I2C_M_RD && msgs[i].addr != 0x40 && 259 + msgs[i].addr != 0x19) { 258 260 /* workaround for a saa7134 i2c bug 259 261 * needed to talk to the mt352 demux 260 262 * thanks to pinnacle for the hint */ ··· 280 278 goto err; 281 279 d1printk("%02x", rc); 282 280 msgs[i].buf[byte] = rc; 281 + } 282 + /* discard mysterious extra byte when reading 283 + from Samsung S5H1411. i2c bus gets error 284 + if we do not. */ 285 + if (0x19 == msgs[i].addr) { 286 + d1printk(" ?"); 287 + rc = i2c_recv_byte(dev); 288 + if (rc < 0) 289 + goto err; 290 + d1printk("%02x", rc); 283 291 } 284 292 } else { 285 293 /* write bytes */
+63
drivers/media/video/saa7134/saa7134-input.c
··· 210 210 return 1; 211 211 } 212 212 213 + /* copied and modified from get_key_msi_tvanywhere_plus() */ 214 + static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key, 215 + u32 *ir_raw) 216 + { 217 + unsigned char b; 218 + unsigned int gpio; 219 + 220 + /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 221 + struct saa7134_dev *dev = ir->c->adapter->algo_data; 222 + if (dev == NULL) { 223 + i2cdprintk("get_key_kworld_pc150u: " 224 + "ir->c->adapter->algo_data is NULL!\n"); 225 + return -EIO; 226 + } 227 + 228 + /* rising SAA7134_GPIO_GPRESCAN reads the status */ 229 + 230 + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 231 + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); 232 + 233 + gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); 234 + 235 + /* GPIO&0x100 is pulsed low when a button is pressed. Don't do 236 + I2C receive if gpio&0x100 is not low. */ 237 + 238 + if (gpio & 0x100) 239 + return 0; /* No button press */ 240 + 241 + /* GPIO says there is a button press. Get it. */ 242 + 243 + if (1 != i2c_master_recv(ir->c, &b, 1)) { 244 + i2cdprintk("read error\n"); 245 + return -EIO; 246 + } 247 + 248 + /* No button press */ 249 + 250 + if (b == 0xff) 251 + return 0; 252 + 253 + /* Button pressed */ 254 + 255 + dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b); 256 + *ir_key = b; 257 + *ir_raw = b; 258 + return 1; 259 + } 260 + 213 261 static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) 214 262 { 215 263 unsigned char b; ··· 939 891 * otherwise it will miss some keypresses 940 892 */ 941 893 dev->init_data.polling_interval = 50; 894 + info.addr = 0x30; 895 + /* MSI TV@nywhere Plus controller doesn't seem to 896 + respond to probes unless we read something from 897 + an existing device. Weird... 898 + REVISIT: might no longer be needed */ 899 + rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); 900 + dprintk("probe 0x%02x @ %s: %s\n", 901 + msg_msi.addr, dev->i2c_adap.name, 902 + (1 == rc) ? "yes" : "no"); 903 + break; 904 + case SAA7134_BOARD_KWORLD_PC150U: 905 + /* copied and modified from MSI TV@nywhere Plus */ 906 + dev->init_data.name = "Kworld PC150-U"; 907 + dev->init_data.get_key = get_key_kworld_pc150u; 908 + dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; 942 909 info.addr = 0x30; 943 910 /* MSI TV@nywhere Plus controller doesn't seem to 944 911 respond to probes unless we read something from
+3 -2
drivers/media/video/saa7134/saa7134.h
··· 126 126 unsigned users; 127 127 128 128 u32 polling; 129 - u32 last_gpio; 130 - u32 mask_keycode, mask_keydown, mask_keyup; 129 + u32 last_gpio; 130 + u32 mask_keycode, mask_keydown, mask_keyup; 131 131 132 132 bool running; 133 133 bool active; ··· 331 331 #define SAA7134_BOARD_BEHOLD_501 186 332 332 #define SAA7134_BOARD_BEHOLD_503FM 187 333 333 #define SAA7134_BOARD_SENSORAY811_911 188 334 + #define SAA7134_BOARD_KWORLD_PC150U 189 334 335 335 336 #define SAA7134_MAXBOARDS 32 336 337 #define SAA7134_INPUT_MAX 8
+1
include/media/rc-map.h
··· 106 106 #define RC_MAP_IT913X_V2 "rc-it913x-v2" 107 107 #define RC_MAP_KAIOMY "rc-kaiomy" 108 108 #define RC_MAP_KWORLD_315U "rc-kworld-315u" 109 + #define RC_MAP_KWORLD_PC150U "rc-kworld-pc150u" 109 110 #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" 110 111 #define RC_MAP_LEADTEK_Y04G0051 "rc-leadtek-y04g0051" 111 112 #define RC_MAP_LIRC "rc-lirc"