diff options
author | Antti Palosaari <crope@iki.fi> | 2013-06-04 08:17:03 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-06-08 20:55:38 -0400 |
commit | f39fac3e409322d23261e89374a7d9daecfd6acb (patch) | |
tree | e8e3c74db32393da66f3939bda145ae5a0ebd2bd /drivers/media/usb/dvb-usb-v2/rtl28xxu.c | |
parent | 1e41413f9869c4a688b2f937ff50584bd62eeb31 (diff) |
[media] rtl28xxu: reimplement rtl2832u remote controller
Thanks to Rodrigo for original implementation!
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2/rtl28xxu.c')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 152 |
1 files changed, 56 insertions, 96 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index e592662ccc06..416701167434 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c | |||
@@ -1114,17 +1114,6 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
1114 | if (ret) | 1114 | if (ret) |
1115 | goto err; | 1115 | goto err; |
1116 | } else { | 1116 | } else { |
1117 | /* demod_ctl_1 */ | ||
1118 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); | ||
1119 | if (ret) | ||
1120 | goto err; | ||
1121 | |||
1122 | val |= 0x0c; | ||
1123 | |||
1124 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); | ||
1125 | if (ret) | ||
1126 | goto err; | ||
1127 | |||
1128 | /* set output values */ | 1117 | /* set output values */ |
1129 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); | 1118 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); |
1130 | if (ret) | 1119 | if (ret) |
@@ -1249,72 +1238,44 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, | |||
1249 | #if IS_ENABLED(CONFIG_RC_CORE) | 1238 | #if IS_ENABLED(CONFIG_RC_CORE) |
1250 | static int rtl2832u_rc_query(struct dvb_usb_device *d) | 1239 | static int rtl2832u_rc_query(struct dvb_usb_device *d) |
1251 | { | 1240 | { |
1252 | #define TICSAT38KHZTONS(x) ((x) * (1000000000/38000)) | 1241 | int ret, i, len; |
1253 | int ret, i; | ||
1254 | struct rtl28xxu_priv *priv = d->priv; | 1242 | struct rtl28xxu_priv *priv = d->priv; |
1243 | struct ir_raw_event ev; | ||
1255 | u8 buf[128]; | 1244 | u8 buf[128]; |
1256 | int len; | 1245 | static const struct rtl28xxu_reg_val_mask refresh_tab[] = { |
1257 | struct ir_raw_event ev; //encode single ir event (pulse or space) | 1246 | {IR_RX_IF, 0x03, 0xff}, |
1258 | struct rtl28xxu_xreg_val rc_sys_init_tab[] = { | 1247 | {IR_RX_BUF_CTRL, 0x80, 0xff}, |
1259 | { SYS_DEMOD_CTL1, OP_AND, 0xfb }, | 1248 | {IR_RX_CTRL, 0x80, 0xff}, |
1260 | { SYS_DEMOD_CTL1, OP_AND, 0xf7 }, | 1249 | }; |
1261 | { USB_CTRL, OP_OR , 0x20 }, | ||
1262 | { SYS_SYS1, OP_AND, 0xf7 }, | ||
1263 | { SYS_GPIO_OUT_EN, OP_OR , 0x08 }, | ||
1264 | { SYS_GPIO_OUT_VAL, OP_OR , 0x08 }, | ||
1265 | }; // system hard init | ||
1266 | struct rtl28xxu_reg_val rc_init_tab[] = { | ||
1267 | { IR_RX_CTRL, 0x20 }, | ||
1268 | { IR_RX_BUF_CTRL, 0x80 }, | ||
1269 | { IR_RX_IF, 0xff }, | ||
1270 | { IR_RX_IE, 0xff }, | ||
1271 | { IR_MAX_DURATION0, 0xd0 }, | ||
1272 | { IR_MAX_DURATION1, 0x07 }, | ||
1273 | { IR_IDLE_LEN0, 0xc0 }, | ||
1274 | { IR_IDLE_LEN1, 0x00 }, | ||
1275 | { IR_GLITCH_LEN, 0x03 }, | ||
1276 | { IR_RX_CLK, 0x09 }, | ||
1277 | { IR_RX_CFG, 0x1c }, | ||
1278 | { IR_MAX_H_TOL_LEN, 0x1e }, | ||
1279 | { IR_MAX_L_TOL_LEN, 0x1e }, | ||
1280 | { IR_RX_CTRL, 0x80 }, | ||
1281 | }; // hard init | ||
1282 | struct rtl28xxu_reg_val rc_reinit_tab[] = { | ||
1283 | { IR_RX_CTRL, 0x20 }, | ||
1284 | { IR_RX_BUF_CTRL, 0x80 }, | ||
1285 | { IR_RX_IF, 0xff }, | ||
1286 | { IR_RX_IE, 0xff }, | ||
1287 | { IR_RX_CTRL, 0x80 }, | ||
1288 | }; // reinit IR | ||
1289 | struct rtl28xxu_reg_val rc_clear_tab[] = { | ||
1290 | { IR_RX_IF, 0x03 }, | ||
1291 | { IR_RX_BUF_CTRL, 0x80 }, | ||
1292 | { IR_RX_CTRL, 0x80 }, | ||
1293 | }; // clear reception | ||
1294 | 1250 | ||
1295 | /* init remote controller */ | 1251 | /* init remote controller */ |
1296 | if (!priv->rc_active) { | 1252 | if (!priv->rc_active) { |
1297 | for (i = 0; i < ARRAY_SIZE(rc_sys_init_tab); i++) { | 1253 | static const struct rtl28xxu_reg_val_mask init_tab[] = { |
1298 | ret = rtl28xx_rd_reg(d, rc_sys_init_tab[i].reg, &buf[0]); | 1254 | {SYS_DEMOD_CTL1, 0x00, 0x04}, |
1299 | if (ret) | 1255 | {SYS_DEMOD_CTL1, 0x00, 0x08}, |
1300 | goto err; | 1256 | {USB_CTRL, 0x20, 0x20}, |
1301 | if (rc_sys_init_tab[i].op == OP_AND) { | 1257 | {SYS_GPIO_DIR, 0x00, 0x08}, |
1302 | buf[0] &= rc_sys_init_tab[i].mask; | 1258 | {SYS_GPIO_OUT_EN, 0x08, 0x08}, |
1303 | } | 1259 | {SYS_GPIO_OUT_VAL, 0x08, 0x08}, |
1304 | else {//OP_OR | 1260 | {IR_MAX_DURATION0, 0xd0, 0xff}, |
1305 | buf[0] |= rc_sys_init_tab[i].mask; | 1261 | {IR_MAX_DURATION1, 0x07, 0xff}, |
1306 | } | 1262 | {IR_IDLE_LEN0, 0xc0, 0xff}, |
1307 | ret = rtl28xx_wr_reg(d, rc_sys_init_tab[i].reg, | 1263 | {IR_IDLE_LEN1, 0x00, 0xff}, |
1308 | buf[0]); | 1264 | {IR_GLITCH_LEN, 0x03, 0xff}, |
1309 | if (ret) | 1265 | {IR_RX_CLK, 0x09, 0xff}, |
1310 | goto err; | 1266 | {IR_RX_CFG, 0x1c, 0xff}, |
1311 | } | 1267 | {IR_MAX_H_TOL_LEN, 0x1e, 0xff}, |
1312 | for (i = 0; i < ARRAY_SIZE(rc_init_tab); i++) { | 1268 | {IR_MAX_L_TOL_LEN, 0x1e, 0xff}, |
1313 | ret = rtl28xx_wr_reg(d, rc_init_tab[i].reg, | 1269 | {IR_RX_CTRL, 0x80, 0xff}, |
1314 | rc_init_tab[i].val); | 1270 | }; |
1271 | |||
1272 | for (i = 0; i < ARRAY_SIZE(init_tab); i++) { | ||
1273 | ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg, | ||
1274 | init_tab[i].val, init_tab[i].mask); | ||
1315 | if (ret) | 1275 | if (ret) |
1316 | goto err; | 1276 | goto err; |
1317 | } | 1277 | } |
1278 | |||
1318 | priv->rc_active = true; | 1279 | priv->rc_active = true; |
1319 | } | 1280 | } |
1320 | 1281 | ||
@@ -1323,57 +1284,56 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) | |||
1323 | goto err; | 1284 | goto err; |
1324 | 1285 | ||
1325 | if (buf[0] != 0x83) | 1286 | if (buf[0] != 0x83) |
1326 | goto err; | 1287 | goto exit; |
1327 | 1288 | ||
1328 | ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); | 1289 | ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); |
1329 | if (ret) | 1290 | if (ret) |
1330 | goto err; | 1291 | goto err; |
1331 | 1292 | ||
1332 | len = buf[0]; | 1293 | len = buf[0]; |
1333 | ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); | ||
1334 | 1294 | ||
1335 | /* pass raw IR to Kernel IR decoder */ | 1295 | /* read raw code from hw */ |
1336 | init_ir_raw_event(&ev); | 1296 | ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); |
1337 | ir_raw_event_reset(d->rc_dev); | 1297 | if (ret) |
1338 | ev.pulse=1; | 1298 | goto err; |
1339 | for(i=0; true; ++i) { // conver count to time | ||
1340 | if (i >= len || !(buf[i] & 0x80) != !(ev.pulse)) {//end or transition pulse/space: flush | ||
1341 | ir_raw_event_store(d->rc_dev, &ev); | ||
1342 | ev.duration = 0; | ||
1343 | } | ||
1344 | if (i >= len) | ||
1345 | break; | ||
1346 | ev.pulse = buf[i] >> 7; | ||
1347 | ev.duration += TICSAT38KHZTONS(((u32)(buf[i] & 0x7F)) << 1); | ||
1348 | } | ||
1349 | ir_raw_event_handle(d->rc_dev); | ||
1350 | 1299 | ||
1351 | for (i = 0; i < ARRAY_SIZE(rc_clear_tab); i++) { | 1300 | /* let hw receive new code */ |
1352 | ret = rtl28xx_wr_reg(d, rc_clear_tab[i].reg, | 1301 | for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) { |
1353 | rc_clear_tab[i].val); | 1302 | ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg, |
1303 | refresh_tab[i].val, refresh_tab[i].mask); | ||
1354 | if (ret) | 1304 | if (ret) |
1355 | goto err; | 1305 | goto err; |
1356 | } | 1306 | } |
1357 | 1307 | ||
1308 | /* pass data to Kernel IR decoder */ | ||
1309 | init_ir_raw_event(&ev); | ||
1310 | |||
1311 | for (i = 0; i < len; i++) { | ||
1312 | ev.pulse = buf[i] >> 7; | ||
1313 | ev.duration = 50800 * (buf[i] & 0x7f); | ||
1314 | ir_raw_event_store_with_filter(d->rc_dev, &ev); | ||
1315 | } | ||
1316 | |||
1317 | /* 'flush' ir_raw_event_store_with_filter() */ | ||
1318 | ir_raw_event_set_idle(d->rc_dev, true); | ||
1319 | ir_raw_event_handle(d->rc_dev); | ||
1320 | exit: | ||
1358 | return ret; | 1321 | return ret; |
1359 | err: | 1322 | err: |
1360 | for (i = 0; i < ARRAY_SIZE(rc_reinit_tab); i++) { | ||
1361 | ret = rtl28xx_wr_reg(d, rc_reinit_tab[i].reg, | ||
1362 | rc_reinit_tab[i].val); | ||
1363 | } | ||
1364 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | 1323 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
1365 | return ret; | 1324 | return ret; |
1366 | #undef TICSAT38KHZTONS | ||
1367 | } | 1325 | } |
1368 | 1326 | ||
1369 | static int rtl2832u_get_rc_config(struct dvb_usb_device *d, | 1327 | static int rtl2832u_get_rc_config(struct dvb_usb_device *d, |
1370 | struct dvb_usb_rc *rc) | 1328 | struct dvb_usb_rc *rc) |
1371 | { | 1329 | { |
1372 | rc->map_name = RC_MAP_EMPTY; | 1330 | /* load empty to enable rc */ |
1331 | if (!rc->map_name) | ||
1332 | rc->map_name = RC_MAP_EMPTY; | ||
1373 | rc->allowed_protos = RC_BIT_ALL; | 1333 | rc->allowed_protos = RC_BIT_ALL; |
1334 | rc->driver_type = RC_DRIVER_IR_RAW; | ||
1374 | rc->query = rtl2832u_rc_query; | 1335 | rc->query = rtl2832u_rc_query; |
1375 | rc->interval = 400; | 1336 | rc->interval = 400; |
1376 | rc->driver_type = RC_DRIVER_IR_RAW; | ||
1377 | 1337 | ||
1378 | return 0; | 1338 | return 0; |
1379 | } | 1339 | } |