diff options
author | Antti Palosaari <crope@iki.fi> | 2011-09-05 22:33:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-07 07:33:15 -0500 |
commit | 05cd37def5e697e158470d826cb75c5607c04bd1 (patch) | |
tree | 73e068946c2bea65be8756c80c31a698dca8865b /drivers/media/dvb/dvb-usb/anysee.c | |
parent | be94351e592cb71fb61aa8eeed7bf3f877dc6fff (diff) |
[media] anysee: CI/CAM support
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/anysee.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/anysee.c | 269 |
1 files changed, 236 insertions, 33 deletions
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 28c7b232c4a8..0bc1372aac18 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
@@ -130,6 +130,29 @@ static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, | |||
130 | return anysee_write_reg(d, reg, val); | 130 | return anysee_write_reg(d, reg, val); |
131 | } | 131 | } |
132 | 132 | ||
133 | /* read single register with mask */ | ||
134 | static int anysee_rd_reg_mask(struct dvb_usb_device *d, u16 reg, u8 *val, | ||
135 | u8 mask) | ||
136 | { | ||
137 | int ret, i; | ||
138 | u8 tmp; | ||
139 | |||
140 | ret = anysee_read_reg(d, reg, &tmp); | ||
141 | if (ret) | ||
142 | return ret; | ||
143 | |||
144 | tmp &= mask; | ||
145 | |||
146 | /* find position of the first bit */ | ||
147 | for (i = 0; i < 8; i++) { | ||
148 | if ((mask >> i) & 0x01) | ||
149 | break; | ||
150 | } | ||
151 | *val = tmp >> i; | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
133 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) | 156 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) |
134 | { | 157 | { |
135 | u8 buf[] = {CMD_GET_HW_INFO}; | 158 | u8 buf[] = {CMD_GET_HW_INFO}; |
@@ -157,22 +180,6 @@ static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) | |||
157 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | 180 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); |
158 | } | 181 | } |
159 | 182 | ||
160 | static int anysee_init(struct dvb_usb_device *d) | ||
161 | { | ||
162 | int ret; | ||
163 | /* LED light */ | ||
164 | ret = anysee_led_ctrl(d, 0x01, 0x03); | ||
165 | if (ret) | ||
166 | return ret; | ||
167 | |||
168 | /* enable IR */ | ||
169 | ret = anysee_ir_ctrl(d, 1); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /* I2C */ | 183 | /* I2C */ |
177 | static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | 184 | static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, |
178 | int num) | 185 | int num) |
@@ -298,7 +305,7 @@ static struct tda10023_config anysee_tda10023_tda18212_config = { | |||
298 | .pll_m = 12, | 305 | .pll_m = 12, |
299 | .pll_p = 3, | 306 | .pll_p = 3, |
300 | .pll_n = 1, | 307 | .pll_n = 1, |
301 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | 308 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_B, |
302 | .deltaf = 0xba02, | 309 | .deltaf = 0xba02, |
303 | }; | 310 | }; |
304 | 311 | ||
@@ -802,11 +809,6 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
802 | /* E7 TC */ | 809 | /* E7 TC */ |
803 | /* E7 PTC */ | 810 | /* E7 PTC */ |
804 | 811 | ||
805 | /* enable transport stream on IOA[7] */ | ||
806 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | ||
807 | if (ret) | ||
808 | goto error; | ||
809 | |||
810 | if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) { | 812 | if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) { |
811 | /* disable DVB-T demod on IOD[6] */ | 813 | /* disable DVB-T demod on IOD[6] */ |
812 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), | 814 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), |
@@ -848,6 +850,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
848 | adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = | 850 | adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = |
849 | anysee_i2c_gate_ctrl; | 851 | anysee_i2c_gate_ctrl; |
850 | 852 | ||
853 | state->has_ci = true; | ||
854 | |||
851 | break; | 855 | break; |
852 | case ANYSEE_HW_508S2: /* 19 */ | 856 | case ANYSEE_HW_508S2: /* 19 */ |
853 | case ANYSEE_HW_508PS2: /* 22 */ | 857 | case ANYSEE_HW_508PS2: /* 22 */ |
@@ -857,11 +861,6 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
857 | if (state->fe_id) | 861 | if (state->fe_id) |
858 | break; | 862 | break; |
859 | 863 | ||
860 | /* enable transport stream on IOA[7] */ | ||
861 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | ||
862 | if (ret) | ||
863 | goto error; | ||
864 | |||
865 | /* enable DVB-S/S2 demod on IOE[5] */ | 864 | /* enable DVB-S/S2 demod on IOE[5] */ |
866 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); | 865 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); |
867 | if (ret) | 866 | if (ret) |
@@ -871,15 +870,12 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
871 | adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, | 870 | adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, |
872 | &adap->dev->i2c_adap, 0); | 871 | &adap->dev->i2c_adap, 0); |
873 | 872 | ||
873 | state->has_ci = true; | ||
874 | |||
874 | break; | 875 | break; |
875 | case ANYSEE_HW_508T2C: /* 20 */ | 876 | case ANYSEE_HW_508T2C: /* 20 */ |
876 | /* E7 T2C */ | 877 | /* E7 T2C */ |
877 | 878 | ||
878 | /* enable transport stream on IOA[7] */ | ||
879 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | ||
880 | if (ret) | ||
881 | goto error; | ||
882 | |||
883 | /* enable DVB-T/T2/C demod on IOE[5] */ | 879 | /* enable DVB-T/T2/C demod on IOE[5] */ |
884 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); | 880 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); |
885 | if (ret) | 881 | if (ret) |
@@ -897,6 +893,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
897 | &adap->dev->i2c_adap, adap->fe_adap[0].fe); | 893 | &adap->dev->i2c_adap, adap->fe_adap[0].fe); |
898 | } | 894 | } |
899 | 895 | ||
896 | state->has_ci = true; | ||
897 | |||
900 | break; | 898 | break; |
901 | } | 899 | } |
902 | 900 | ||
@@ -1042,6 +1040,201 @@ static int anysee_rc_query(struct dvb_usb_device *d) | |||
1042 | return 0; | 1040 | return 0; |
1043 | } | 1041 | } |
1044 | 1042 | ||
1043 | static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot, | ||
1044 | int addr) | ||
1045 | { | ||
1046 | struct dvb_usb_device *d = ci->data; | ||
1047 | int ret; | ||
1048 | u8 buf[] = {CMD_CI, 0x02, 0x40 | addr >> 8, addr & 0xff, 0x00, 1}; | ||
1049 | u8 val; | ||
1050 | |||
1051 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1); | ||
1052 | if (ret) | ||
1053 | return ret; | ||
1054 | |||
1055 | return val; | ||
1056 | } | ||
1057 | |||
1058 | static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot, | ||
1059 | int addr, u8 val) | ||
1060 | { | ||
1061 | struct dvb_usb_device *d = ci->data; | ||
1062 | int ret; | ||
1063 | u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val}; | ||
1064 | |||
1065 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
1066 | if (ret) | ||
1067 | return ret; | ||
1068 | |||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot, | ||
1073 | u8 addr) | ||
1074 | { | ||
1075 | struct dvb_usb_device *d = ci->data; | ||
1076 | int ret; | ||
1077 | u8 buf[] = {CMD_CI, 0x04, 0x40, addr, 0x00, 1}; | ||
1078 | u8 val; | ||
1079 | |||
1080 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1); | ||
1081 | if (ret) | ||
1082 | return ret; | ||
1083 | |||
1084 | return val; | ||
1085 | } | ||
1086 | |||
1087 | static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot, | ||
1088 | u8 addr, u8 val) | ||
1089 | { | ||
1090 | struct dvb_usb_device *d = ci->data; | ||
1091 | int ret; | ||
1092 | u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val}; | ||
1093 | |||
1094 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
1095 | if (ret) | ||
1096 | return ret; | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) | ||
1102 | { | ||
1103 | struct dvb_usb_device *d = ci->data; | ||
1104 | int ret; | ||
1105 | struct anysee_state *state = d->priv; | ||
1106 | |||
1107 | state->ci_cam_ready = jiffies + msecs_to_jiffies(1000); | ||
1108 | |||
1109 | ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); | ||
1110 | if (ret) | ||
1111 | return ret; | ||
1112 | |||
1113 | msleep(300); | ||
1114 | |||
1115 | ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); | ||
1116 | if (ret) | ||
1117 | return ret; | ||
1118 | |||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1122 | static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot) | ||
1123 | { | ||
1124 | struct dvb_usb_device *d = ci->data; | ||
1125 | int ret; | ||
1126 | |||
1127 | ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); | ||
1128 | if (ret) | ||
1129 | return ret; | ||
1130 | |||
1131 | msleep(30); | ||
1132 | |||
1133 | ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); | ||
1134 | if (ret) | ||
1135 | return ret; | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot) | ||
1141 | { | ||
1142 | struct dvb_usb_device *d = ci->data; | ||
1143 | int ret; | ||
1144 | |||
1145 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02); | ||
1146 | if (ret) | ||
1147 | return ret; | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, | ||
1153 | int open) | ||
1154 | { | ||
1155 | struct dvb_usb_device *d = ci->data; | ||
1156 | struct anysee_state *state = d->priv; | ||
1157 | int ret; | ||
1158 | u8 tmp; | ||
1159 | |||
1160 | ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40); | ||
1161 | if (ret) | ||
1162 | return ret; | ||
1163 | |||
1164 | if (tmp == 0) { | ||
1165 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT; | ||
1166 | if (time_after(jiffies, state->ci_cam_ready)) | ||
1167 | ret |= DVB_CA_EN50221_POLL_CAM_READY; | ||
1168 | } | ||
1169 | |||
1170 | return ret; | ||
1171 | } | ||
1172 | |||
1173 | static int anysee_ci_init(struct dvb_usb_device *d) | ||
1174 | { | ||
1175 | struct anysee_state *state = d->priv; | ||
1176 | int ret; | ||
1177 | |||
1178 | state->ci.owner = THIS_MODULE; | ||
1179 | state->ci.read_attribute_mem = anysee_ci_read_attribute_mem; | ||
1180 | state->ci.write_attribute_mem = anysee_ci_write_attribute_mem; | ||
1181 | state->ci.read_cam_control = anysee_ci_read_cam_control; | ||
1182 | state->ci.write_cam_control = anysee_ci_write_cam_control; | ||
1183 | state->ci.slot_reset = anysee_ci_slot_reset; | ||
1184 | state->ci.slot_shutdown = anysee_ci_slot_shutdown; | ||
1185 | state->ci.slot_ts_enable = anysee_ci_slot_ts_enable; | ||
1186 | state->ci.poll_slot_status = anysee_ci_poll_slot_status; | ||
1187 | state->ci.data = d; | ||
1188 | |||
1189 | ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); | ||
1190 | if (ret) | ||
1191 | return ret; | ||
1192 | |||
1193 | ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); | ||
1194 | if (ret) | ||
1195 | return ret; | ||
1196 | |||
1197 | return 0; | ||
1198 | } | ||
1199 | |||
1200 | static void anysee_ci_release(struct dvb_usb_device *d) | ||
1201 | { | ||
1202 | struct anysee_state *state = d->priv; | ||
1203 | |||
1204 | /* detach CI */ | ||
1205 | if (state->has_ci) | ||
1206 | dvb_ca_en50221_release(&state->ci); | ||
1207 | |||
1208 | return; | ||
1209 | } | ||
1210 | |||
1211 | static int anysee_init(struct dvb_usb_device *d) | ||
1212 | { | ||
1213 | struct anysee_state *state = d->priv; | ||
1214 | int ret; | ||
1215 | |||
1216 | /* LED light */ | ||
1217 | ret = anysee_led_ctrl(d, 0x01, 0x03); | ||
1218 | if (ret) | ||
1219 | return ret; | ||
1220 | |||
1221 | /* enable IR */ | ||
1222 | ret = anysee_ir_ctrl(d, 1); | ||
1223 | if (ret) | ||
1224 | return ret; | ||
1225 | |||
1226 | /* attach CI */ | ||
1227 | if (state->has_ci) { | ||
1228 | ret = anysee_ci_init(d); | ||
1229 | if (ret) { | ||
1230 | state->has_ci = false; | ||
1231 | return ret; | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1045 | /* DVB USB Driver stuff */ | 1238 | /* DVB USB Driver stuff */ |
1046 | static struct dvb_usb_device_properties anysee_properties; | 1239 | static struct dvb_usb_device_properties anysee_properties; |
1047 | 1240 | ||
@@ -1083,6 +1276,16 @@ static int anysee_probe(struct usb_interface *intf, | |||
1083 | return anysee_init(d); | 1276 | return anysee_init(d); |
1084 | } | 1277 | } |
1085 | 1278 | ||
1279 | static void anysee_disconnect(struct usb_interface *intf) | ||
1280 | { | ||
1281 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
1282 | |||
1283 | anysee_ci_release(d); | ||
1284 | dvb_usb_device_exit(intf); | ||
1285 | |||
1286 | return; | ||
1287 | } | ||
1288 | |||
1086 | static struct usb_device_id anysee_table[] = { | 1289 | static struct usb_device_id anysee_table[] = { |
1087 | { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, | 1290 | { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, |
1088 | { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, | 1291 | { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, |
@@ -1160,7 +1363,7 @@ static struct dvb_usb_device_properties anysee_properties = { | |||
1160 | static struct usb_driver anysee_driver = { | 1363 | static struct usb_driver anysee_driver = { |
1161 | .name = "dvb_usb_anysee", | 1364 | .name = "dvb_usb_anysee", |
1162 | .probe = anysee_probe, | 1365 | .probe = anysee_probe, |
1163 | .disconnect = dvb_usb_device_exit, | 1366 | .disconnect = anysee_disconnect, |
1164 | .id_table = anysee_table, | 1367 | .id_table = anysee_table, |
1165 | }; | 1368 | }; |
1166 | 1369 | ||