33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/slab.h>
36 #include <linux/sched.h>
38 #include <linux/videodev2.h>
39 #include <linux/i2c.h>
89 #define TUNER_AUDIO_MONO 0
90 #define TUNER_AUDIO_STEREO 1
91 #define TUNER_AUDIO_LANG1 2
92 #define TUNER_AUDIO_LANG2 3
94 #define SAA717X_NTSC_WIDTH (704)
95 #define SAA717X_NTSC_HEIGHT (480)
103 int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
104 unsigned char mm1[6];
109 mm1[0] = (reg >> 8) & 0xff;
113 mm1[4] = (value >> 16) & 0xff;
114 mm1[3] = (value >> 8) & 0xff;
115 mm1[2] = value & 0xff;
117 mm1[2] = value & 0xff;
119 msg.
len = fw_addr ? 5 : 3;
121 v4l2_dbg(2,
debug, sd,
"wrote: reg 0x%03x=%08x\n", reg, value);
127 while (data[0] || data[1]) {
128 saa717x_write(sd, data[0], data[1]);
137 int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
138 unsigned char mm1[2];
139 unsigned char mm2[4] = { 0, 0, 0, 0 };
145 msgs[0].addr = msgs[1].addr = client->
addr;
146 mm1[0] = (reg >> 8) & 0xff;
150 msgs[1].len = fw_addr ? 3 : 1;
155 value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
157 value = mm2[0] & 0xff;
159 v4l2_dbg(2,
debug, sd,
"read: reg 0x%03x=0x%08x\n", reg, value);
165 static u32 reg_init_initialize[] =
637 static u32 reg_init_tuner_input[] = {
645 static u32 reg_init_composite_input[] = {
653 static u32 reg_init_svideo_input[] = {
660 static u32 reg_set_audio_template[4][2] =
693 static void get_inf_dev_status(
struct v4l2_subdev *sd,
694 int *dual_flag,
int *stereo_flag)
698 static char *stdres[0x20] = {
699 [0x00] =
"no standard detected",
700 [0x01] =
"B/G (in progress)",
701 [0x02] =
"D/K (in progress)",
702 [0x03] =
"M (in progress)",
705 [0x05] =
"B/G NICAM",
706 [0x06] =
"D/K A2 (1)",
707 [0x07] =
"D/K A2 (2)",
708 [0x08] =
"D/K A2 (3)",
709 [0x09] =
"D/K NICAM",
717 [0x0f] =
"FM radio / IF 10.7 / 50 deemp",
718 [0x10] =
"FM radio / IF 10.7 / 75 deemp",
719 [0x11] =
"FM radio / IF sel / 50 deemp",
720 [0x12] =
"FM radio / IF sel / 75 deemp",
722 [0x13 ... 0x1e] =
"unknown",
723 [0x1f] =
"??? [in progress]",
727 *dual_flag = *stereo_flag = 0;
732 reg_data3 = saa717x_read(sd, 0x0528);
734 v4l2_dbg(1,
debug, sd,
"tvaudio thread status: 0x%x [%s%s%s]\n",
735 reg_data3, stdres[reg_data3 & 0x1f],
736 (reg_data3 & 0x000020) ?
",stereo" :
"",
737 (reg_data3 & 0x000040) ?
",dual" :
"");
739 "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
740 (reg_data3 & 0x000080) ?
" A2/EIAJ pilot tone " :
"",
741 (reg_data3 & 0x000100) ?
" A2/EIAJ dual " :
"",
742 (reg_data3 & 0x000200) ?
" A2/EIAJ stereo " :
"",
743 (reg_data3 & 0x000400) ?
" A2/EIAJ noise mute " :
"",
745 (reg_data3 & 0x000800) ?
" BTSC/FM radio pilot " :
"",
746 (reg_data3 & 0x001000) ?
" SAP carrier " :
"",
747 (reg_data3 & 0x002000) ?
" BTSC stereo noise mute " :
"",
748 (reg_data3 & 0x004000) ?
" SAP noise mute " :
"",
749 (reg_data3 & 0x008000) ?
" VDSP " :
"",
751 (reg_data3 & 0x010000) ?
" NICST " :
"",
752 (reg_data3 & 0x020000) ?
" NICDU " :
"",
753 (reg_data3 & 0x040000) ?
" NICAM muted " :
"",
754 (reg_data3 & 0x080000) ?
" NICAM reserve sound " :
"",
756 (reg_data3 & 0x100000) ?
" init done " :
"");
758 if (reg_data3 & 0x000220) {
763 if (reg_data3 & 0x000140) {
772 v4l2_dbg(1,
debug, sd,
"writing registers to set audio mode by set %d\n",
775 saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
776 saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
785 unsigned int work_l, work_r;
803 val = mute | (mute << 8);
809 saa717x_write(sd, 0x480, val);
814 saa717x_write(sd, 0x488, val);
822 static const struct {
844 task_shift = task * 0x40;
845 for (i = 0; i <
count; i++)
846 if (vals[i].xpsc == prescale)
852 saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
854 saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
856 saa717x_write(sd, 0x62 + task_shift,
857 (vals[i].xc2_1 << 3) | vals[i].xdcg);
859 saa717x_write(sd, 0x63 + task_shift,
860 (vals[i].vpfy << 2) | vals[i].vpfy);
864 static void set_v_scale(
struct v4l2_subdev *sd,
int task,
int yscale)
868 task_shift = task * 0x40;
870 saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
872 saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
882 saa717x_write(sd, 0x10a, ctrl->
val);
886 saa717x_write(sd, 0x10b, ctrl->
val);
890 saa717x_write(sd, 0x10c, ctrl->
val);
894 saa717x_write(sd, 0x10d, ctrl->
val);
920 set_audio_regs(sd, state);
924 static int saa717x_s_video_routing(
struct v4l2_subdev *sd,
928 int is_tuner = input & 0x80;
935 if (input > 9 || input == 5)
938 if (decoder->
input != input) {
939 int input_line =
input;
941 decoder->
input = input_line;
943 input_line >= 6 ?
"S-Video" :
"Composite",
947 saa717x_write(sd, 0x102,
948 (saa717x_read(sd, 0x102) & 0xf0) |
952 saa717x_write(sd, 0x109,
953 (saa717x_read(sd, 0x109) & 0x7f) |
954 (input_line < 6 ? 0x0 : 0x80));
967 saa717x_write_regs(sd, reg_init_tuner_input);
968 else if (input_line >= 6)
969 saa717x_write_regs(sd, reg_init_svideo_input);
971 saa717x_write_regs(sd, reg_init_composite_input);
977 #ifdef CONFIG_VIDEO_ADV_DEBUG
980 struct i2c_client *client = v4l2_get_subdevdata(sd);
986 reg->
val = saa717x_read(sd, reg->
reg);
993 struct i2c_client *client = v4l2_get_subdevdata(sd);
995 u8 val = reg->
val & 0xff;
1001 saa717x_write(sd, addr, val);
1006 static int saa717x_s_mbus_fmt(
struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *
fmt)
1016 if (fmt->width < 1 || fmt->width > 1440)
1018 if (fmt->height < 1 || fmt->height > 960)
1034 set_h_prescale(sd, 0, prescale);
1035 set_h_prescale(sd, 1, prescale);
1039 saa717x_write(sd, 0x6C, (
u8)(h_scale & 0xFF));
1040 saa717x_write(sd, 0x6D, (
u8)((h_scale >> 8) & 0xFF));
1042 saa717x_write(sd, 0xAC, (
u8)(h_scale & 0xFF));
1043 saa717x_write(sd, 0xAD, (
u8)((h_scale >> 8) & 0xFF));
1046 set_v_scale(sd, 0, v_scale);
1047 set_v_scale(sd, 1, v_scale);
1052 saa717x_write(sd, 0x5C, (
u8)(fmt->width & 0xFF));
1053 saa717x_write(sd, 0x5D, (
u8)((fmt->width >> 8) & 0xFF));
1055 saa717x_write(sd, 0x9C, (
u8)(fmt->width & 0xFF));
1056 saa717x_write(sd, 0x9D, (
u8)((fmt->width >> 8) & 0xFF));
1060 saa717x_write(sd, 0x5E, (
u8)(fmt->height & 0xFF));
1061 saa717x_write(sd, 0x5F, (
u8)((fmt->height >> 8) & 0xFF));
1063 saa717x_write(sd, 0x9E, (
u8)(fmt->height & 0xFF));
1064 saa717x_write(sd, 0x9F, (
u8)((fmt->height >> 8) & 0xFF));
1068 static int saa717x_s_radio(
struct v4l2_subdev *sd)
1088 static int saa717x_s_audio_routing(
struct v4l2_subdev *sd,
1096 "set decoder audio input to %d\n",
1098 set_audio_regs(sd, decoder);
1109 enable ?
"enable" :
"disable");
1111 saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1121 "MONO",
"STEREO",
"LANG1",
"LANG2/SAP"
1153 int dual_f, stereo_f;
1157 get_inf_dev_status(sd, &dual_f, &stereo_f);
1163 if ((dual_f == 0) && (stereo_f == 0)) {
1169 if (stereo_f == 1) {
1193 static int saa717x_log_status(
struct v4l2_subdev *sd)
1204 .s_ctrl = saa717x_s_ctrl,
1208 #ifdef CONFIG_VIDEO_ADV_DEBUG
1209 .g_register = saa717x_g_register,
1210 .s_register = saa717x_s_register,
1212 .s_std = saa717x_s_std,
1220 .log_status = saa717x_log_status,
1224 .g_tuner = saa717x_g_tuner,
1225 .s_tuner = saa717x_s_tuner,
1226 .s_radio = saa717x_s_radio,
1230 .s_routing = saa717x_s_video_routing,
1231 .s_mbus_fmt = saa717x_s_mbus_fmt,
1232 .s_stream = saa717x_s_stream,
1236 .s_routing = saa717x_s_audio_routing,
1240 .core = &saa717x_core_ops,
1241 .tuner = &saa717x_tuner_ops,
1242 .audio = &saa717x_audio_ops,
1243 .video = &saa717x_video_ops,
1252 static int saa717x_probe(
struct i2c_client *client,
1266 if (decoder ==
NULL)
1272 if (saa717x_write(sd, 0x5a4, 0xfe) &&
1273 saa717x_write(sd, 0x5a5, 0x0f) &&
1274 saa717x_write(sd, 0x5a6, 0x00) &&
1275 saa717x_write(sd, 0x5a7, 0x01))
1276 id = saa717x_read(sd, 0x5a0);
1277 if (
id != 0xc2 &&
id != 0x32 &&
id != 0xf2 &&
id != 0x6c) {
1278 v4l2_dbg(1,
debug, sd,
"saa717x not found (id=%02x)\n",
id);
1284 else if (
id == 0x32)
1286 else if (
id == 0x6c)
1290 v4l2_info(sd,
"%s found @ 0x%x (%s)\n", p,
1293 hdl = &decoder->
hdl;
1324 decoder->
input = -1;
1341 saa717x_write_regs(sd, reg_init_initialize);
1350 static int saa717x_remove(
struct i2c_client *client)
1352 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1356 kfree(to_state(sd));
1373 .probe = saa717x_probe,
1374 .remove = saa717x_remove,
1375 .id_table = saa717x_id,