Lines Matching +full:playback +full:- +full:sd +full:- +full:lines
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * saa717x - Philips SAA717xHL video decoder driver
8 * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
10 * Changes by T.Adachi (tadachi@tadachi-net.com)
11 * - support audio, video scaler etc, and checked the initialize sequence.
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-ctrls.h>
36 MODULE_PARM_DESC(debug, "Debug level (0-1)");
44 struct v4l2_subdev sd; member
50 int playback; member
63 static inline struct saa717x_state *to_state(struct v4l2_subdev *sd) in to_state() argument
65 return container_of(sd, struct saa717x_state, sd); in to_state()
70 return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd; in to_sd()
73 /* ----------------------------------------------------------------------- */
84 /* ----------------------------------------------------------------------- */
86 static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value) in saa717x_write() argument
88 struct i2c_client *client = v4l2_get_subdevdata(sd); in saa717x_write()
89 struct i2c_adapter *adap = client->adapter; in saa717x_write()
95 msg.addr = client->addr; in saa717x_write()
108 v4l2_dbg(2, debug, sd, "wrote: reg 0x%03x=%08x\n", reg, value); in saa717x_write()
112 static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data) in saa717x_write_regs() argument
115 saa717x_write(sd, data[0], data[1]); in saa717x_write_regs()
120 static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg) in saa717x_read() argument
122 struct i2c_client *client = v4l2_get_subdevdata(sd); in saa717x_read()
123 struct i2c_adapter *adap = client->adapter; in saa717x_read()
132 msgs[0].addr = msgs[1].addr = client->addr; in saa717x_read()
146 v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value); in saa717x_read()
150 /* ----------------------------------------------------------------------- */
222 0x010, 0x010, /* GREEN path gamma curve --- */
237 0x01f, 0x0ff, /* --- GREEN path gamma curve */
239 0x020, 0x010, /* BLUE path gamma curve --- */
254 0x02f, 0x0ff, /* --- BLUE path gamma curve */
256 0x030, 0x010, /* RED path gamma curve --- */
271 0x03f, 0x0ff, /* --- RED path gamma curve */
295 0x46c, 0xbbbb10, /* Digital output selection1-3 */
296 0x470, 0x101010, /* Digital output selection4-6 */
639 /* S-Video */
652 7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
663 7-4:DAC right ch. 3-0:DAC left ch.
680 static void get_inf_dev_status(struct v4l2_subdev *sd, in get_inf_dev_status() argument
719 reg_data3 = saa717x_read(sd, 0x0528); in get_inf_dev_status()
721 v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n", in get_inf_dev_status()
725 v4l2_dbg(1, debug, sd, "detailed status: " in get_inf_dev_status()
746 v4l2_dbg(1, debug, sd, "ST!!!\n"); in get_inf_dev_status()
751 v4l2_dbg(1, debug, sd, "DUAL!!!\n"); in get_inf_dev_status()
757 static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode) in set_audio_mode() argument
759 v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n", in set_audio_mode()
762 saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]); in set_audio_mode()
763 saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]); in set_audio_mode()
767 static int set_audio_regs(struct v4l2_subdev *sd, in set_audio_regs() argument
770 u8 mute = 0xac; /* -84 dB */ in set_audio_regs()
775 saa717x_write(sd, 0x0594, decoder->audio_input); in set_audio_regs()
776 v4l2_dbg(1, debug, sd, "set audio input %d\n", in set_audio_regs()
777 decoder->audio_input); in set_audio_regs()
779 /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */ in set_audio_regs()
780 work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768; in set_audio_regs()
781 work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768; in set_audio_regs()
782 decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40; in set_audio_regs()
783 decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40; in set_audio_regs()
786 /* main volume L[7-0],R[7-0],0x00 24=24dB,-83dB, -84(mute) */ in set_audio_regs()
787 /* def:0dB->6dB(MPG600GR) */ in set_audio_regs()
789 if (decoder->audio_main_mute) { in set_audio_regs()
792 val = (u8)decoder->audio_main_vol_l | in set_audio_regs()
793 ((u8)decoder->audio_main_vol_r << 8); in set_audio_regs()
796 saa717x_write(sd, 0x480, val); in set_audio_regs()
799 val = decoder->audio_main_bass & 0x1f; in set_audio_regs()
800 val |= (decoder->audio_main_treble & 0x1f) << 5; in set_audio_regs()
801 saa717x_write(sd, 0x488, val); in set_audio_regs()
806 static void set_h_prescale(struct v4l2_subdev *sd, in set_h_prescale() argument
839 saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc); in set_h_prescale()
841 saa717x_write(sd, 0x61 + task_shift, vals[i].xacl); in set_h_prescale()
843 saa717x_write(sd, 0x62 + task_shift, in set_h_prescale()
846 saa717x_write(sd, 0x63 + task_shift, in set_h_prescale()
851 static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale) in set_v_scale() argument
857 saa717x_write(sd, 0x70 + task_shift, yscale & 0xff); in set_v_scale()
859 saa717x_write(sd, 0x71 + task_shift, yscale >> 8); in set_v_scale()
864 struct v4l2_subdev *sd = to_sd(ctrl); in saa717x_s_ctrl() local
865 struct saa717x_state *state = to_state(sd); in saa717x_s_ctrl()
867 switch (ctrl->id) { in saa717x_s_ctrl()
869 saa717x_write(sd, 0x10a, ctrl->val); in saa717x_s_ctrl()
873 saa717x_write(sd, 0x10b, ctrl->val); in saa717x_s_ctrl()
877 saa717x_write(sd, 0x10c, ctrl->val); in saa717x_s_ctrl()
881 saa717x_write(sd, 0x10d, ctrl->val); in saa717x_s_ctrl()
885 state->audio_main_mute = ctrl->val; in saa717x_s_ctrl()
889 state->audio_main_volume = ctrl->val; in saa717x_s_ctrl()
893 state->audio_main_balance = ctrl->val; in saa717x_s_ctrl()
897 state->audio_main_treble = ctrl->val; in saa717x_s_ctrl()
901 state->audio_main_bass = ctrl->val; in saa717x_s_ctrl()
907 set_audio_regs(sd, state); in saa717x_s_ctrl()
911 static int saa717x_s_video_routing(struct v4l2_subdev *sd, in saa717x_s_video_routing() argument
914 struct saa717x_state *decoder = to_state(sd); in saa717x_s_video_routing()
919 v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input); in saa717x_s_video_routing()
920 /* inputs from 0-9 are available*/ in saa717x_s_video_routing()
921 /* saa717x have mode0-mode9 but mode5 is reserved. */ in saa717x_s_video_routing()
923 return -EINVAL; in saa717x_s_video_routing()
925 if (decoder->input != input) { in saa717x_s_video_routing()
928 decoder->input = input_line; in saa717x_s_video_routing()
929 v4l2_dbg(1, debug, sd, "now setting %s input %d\n", in saa717x_s_video_routing()
930 input_line >= 6 ? "S-Video" : "Composite", in saa717x_s_video_routing()
934 saa717x_write(sd, 0x102, in saa717x_s_video_routing()
935 (saa717x_read(sd, 0x102) & 0xf0) | in saa717x_s_video_routing()
939 saa717x_write(sd, 0x109, in saa717x_s_video_routing()
940 (saa717x_read(sd, 0x109) & 0x7f) | in saa717x_s_video_routing()
946 set_audio_mode(sd, decoder->tuner_audio_mode); in saa717x_s_video_routing()
949 * S-Video were chosen */ in saa717x_s_video_routing()
950 set_audio_mode(sd, TUNER_AUDIO_STEREO); in saa717x_s_video_routing()
952 /* change initialize procedure (Composite/S-Video) */ in saa717x_s_video_routing()
954 saa717x_write_regs(sd, reg_init_tuner_input); in saa717x_s_video_routing()
956 saa717x_write_regs(sd, reg_init_svideo_input); in saa717x_s_video_routing()
958 saa717x_write_regs(sd, reg_init_composite_input); in saa717x_s_video_routing()
965 static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) in saa717x_g_register() argument
967 reg->val = saa717x_read(sd, reg->reg); in saa717x_g_register()
968 reg->size = 1; in saa717x_g_register()
972 static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) in saa717x_s_register() argument
974 u16 addr = reg->reg & 0xffff; in saa717x_s_register()
975 u8 val = reg->val & 0xff; in saa717x_s_register()
977 saa717x_write(sd, addr, val); in saa717x_s_register()
982 static int saa717x_set_fmt(struct v4l2_subdev *sd, in saa717x_set_fmt() argument
986 struct v4l2_mbus_framefmt *fmt = &format->format; in saa717x_set_fmt()
989 v4l2_dbg(1, debug, sd, "decoder set size\n"); in saa717x_set_fmt()
991 if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED) in saa717x_set_fmt()
992 return -EINVAL; in saa717x_set_fmt()
995 if (fmt->width < 1 || fmt->width > 1440) in saa717x_set_fmt()
996 return -EINVAL; in saa717x_set_fmt()
997 if (fmt->height < 1 || fmt->height > 960) in saa717x_set_fmt()
998 return -EINVAL; in saa717x_set_fmt()
1000 fmt->field = V4L2_FIELD_INTERLACED; in saa717x_set_fmt()
1001 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; in saa717x_set_fmt()
1003 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in saa717x_set_fmt()
1008 prescale = SAA717X_NTSC_WIDTH / fmt->width; in saa717x_set_fmt()
1011 h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width; in saa717x_set_fmt()
1013 v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height; in saa717x_set_fmt()
1016 set_h_prescale(sd, 0, prescale); in saa717x_set_fmt()
1017 set_h_prescale(sd, 1, prescale); in saa717x_set_fmt()
1021 saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF)); in saa717x_set_fmt()
1022 saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF)); in saa717x_set_fmt()
1024 saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF)); in saa717x_set_fmt()
1025 saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF)); in saa717x_set_fmt()
1028 set_v_scale(sd, 0, v_scale); in saa717x_set_fmt()
1029 set_v_scale(sd, 1, v_scale); in saa717x_set_fmt()
1034 saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF)); in saa717x_set_fmt()
1035 saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF)); in saa717x_set_fmt()
1037 saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF)); in saa717x_set_fmt()
1038 saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF)); in saa717x_set_fmt()
1040 /* video number of lines at output */ in saa717x_set_fmt()
1042 saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF)); in saa717x_set_fmt()
1043 saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF)); in saa717x_set_fmt()
1045 saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF)); in saa717x_set_fmt()
1046 saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF)); in saa717x_set_fmt()
1050 static int saa717x_s_radio(struct v4l2_subdev *sd) in saa717x_s_radio() argument
1052 struct saa717x_state *decoder = to_state(sd); in saa717x_s_radio()
1054 decoder->radio = 1; in saa717x_s_radio()
1058 static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) in saa717x_s_std() argument
1060 struct saa717x_state *decoder = to_state(sd); in saa717x_s_std()
1062 v4l2_dbg(1, debug, sd, "decoder set norm "); in saa717x_s_std()
1063 v4l2_dbg(1, debug, sd, "(not yet implemented)\n"); in saa717x_s_std()
1065 decoder->radio = 0; in saa717x_s_std()
1066 decoder->std = std; in saa717x_s_std()
1070 static int saa717x_s_audio_routing(struct v4l2_subdev *sd, in saa717x_s_audio_routing() argument
1073 struct saa717x_state *decoder = to_state(sd); in saa717x_s_audio_routing()
1075 if (input < 3) { /* FIXME! --tadachi */ in saa717x_s_audio_routing()
1076 decoder->audio_input = input; in saa717x_s_audio_routing()
1077 v4l2_dbg(1, debug, sd, in saa717x_s_audio_routing()
1079 decoder->audio_input); in saa717x_s_audio_routing()
1080 set_audio_regs(sd, decoder); in saa717x_s_audio_routing()
1083 return -ERANGE; in saa717x_s_audio_routing()
1086 static int saa717x_s_stream(struct v4l2_subdev *sd, int enable) in saa717x_s_stream() argument
1088 struct saa717x_state *decoder = to_state(sd); in saa717x_s_stream()
1090 v4l2_dbg(1, debug, sd, "decoder %s output\n", in saa717x_s_stream()
1092 decoder->enable = enable; in saa717x_s_stream()
1093 saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26); in saa717x_s_stream()
1098 static int saa717x_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) in saa717x_s_tuner() argument
1100 struct saa717x_state *decoder = to_state(sd); in saa717x_s_tuner()
1108 switch (vt->audmode) { in saa717x_s_tuner()
1123 v4l2_dbg(1, debug, sd, "change audio mode to %s\n", in saa717x_s_tuner()
1125 decoder->tuner_audio_mode = audio_mode; in saa717x_s_tuner()
1128 set_audio_mode(sd, decoder->tuner_audio_mode); in saa717x_s_tuner()
1132 static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) in saa717x_g_tuner() argument
1134 struct saa717x_state *decoder = to_state(sd); in saa717x_g_tuner()
1137 if (decoder->radio) in saa717x_g_tuner()
1139 get_inf_dev_status(sd, &dual_f, &stereo_f); in saa717x_g_tuner()
1141 v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n", in saa717x_g_tuner()
1146 vt->rxsubchans = V4L2_TUNER_SUB_MONO; in saa717x_g_tuner()
1147 v4l2_dbg(1, debug, sd, "DETECT==MONO\n"); in saa717x_g_tuner()
1152 if (vt->audmode == V4L2_TUNER_MODE_STEREO || in saa717x_g_tuner()
1153 vt->audmode == V4L2_TUNER_MODE_LANG1) { in saa717x_g_tuner()
1154 vt->rxsubchans = V4L2_TUNER_SUB_STEREO; in saa717x_g_tuner()
1155 v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n"); in saa717x_g_tuner()
1157 vt->rxsubchans = V4L2_TUNER_SUB_MONO; in saa717x_g_tuner()
1158 v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n"); in saa717x_g_tuner()
1164 if (vt->audmode == V4L2_TUNER_MODE_LANG2) { in saa717x_g_tuner()
1165 vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO; in saa717x_g_tuner()
1166 v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n"); in saa717x_g_tuner()
1168 vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO; in saa717x_g_tuner()
1169 v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n"); in saa717x_g_tuner()
1175 static int saa717x_log_status(struct v4l2_subdev *sd) in saa717x_log_status() argument
1177 struct saa717x_state *state = to_state(sd); in saa717x_log_status()
1179 v4l2_ctrl_handler_log_status(&state->hdl, sd->name); in saa717x_log_status()
1183 /* ----------------------------------------------------------------------- */
1225 /* ----------------------------------------------------------------------- */
1230 /* ----------------------------------------------------------------------- */
1235 struct v4l2_subdev *sd; in saa717x_probe() local
1240 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) in saa717x_probe()
1241 return -EIO; in saa717x_probe()
1243 decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); in saa717x_probe()
1245 return -ENOMEM; in saa717x_probe()
1247 sd = &decoder->sd; in saa717x_probe()
1248 v4l2_i2c_subdev_init(sd, client, &saa717x_ops); in saa717x_probe()
1250 if (saa717x_write(sd, 0x5a4, 0xfe) && in saa717x_probe()
1251 saa717x_write(sd, 0x5a5, 0x0f) && in saa717x_probe()
1252 saa717x_write(sd, 0x5a6, 0x00) && in saa717x_probe()
1253 saa717x_write(sd, 0x5a7, 0x01)) in saa717x_probe()
1254 id = saa717x_read(sd, 0x5a0); in saa717x_probe()
1256 v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id); in saa717x_probe()
1257 return -ENODEV; in saa717x_probe()
1267 v4l2_info(sd, "%s found @ 0x%x (%s)\n", p, in saa717x_probe()
1268 client->addr << 1, client->adapter->name); in saa717x_probe()
1270 hdl = &decoder->hdl; in saa717x_probe()
1280 V4L2_CID_HUE, -128, 127, 1, 0); in saa717x_probe()
1286 V4L2_CID_AUDIO_BASS, -16, 15, 1, 0); in saa717x_probe()
1288 V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0); in saa717x_probe()
1291 sd->ctrl_handler = hdl; in saa717x_probe()
1292 if (hdl->error) { in saa717x_probe()
1293 int err = hdl->error; in saa717x_probe()
1299 decoder->std = V4L2_STD_NTSC; in saa717x_probe()
1300 decoder->input = -1; in saa717x_probe()
1301 decoder->enable = 1; in saa717x_probe()
1304 decoder->playback = 0; /* initially capture mode used */ in saa717x_probe()
1305 decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */ in saa717x_probe()
1307 decoder->audio_input = 2; /* FIXME!! */ in saa717x_probe()
1309 decoder->tuner_audio_mode = TUNER_AUDIO_STEREO; in saa717x_probe()
1311 decoder->audio_main_vol_l = 6; in saa717x_probe()
1312 decoder->audio_main_vol_r = 6; in saa717x_probe()
1314 v4l2_dbg(1, debug, sd, "writing init values\n"); in saa717x_probe()
1317 saa717x_write_regs(sd, reg_init_initialize); in saa717x_probe()
1328 struct v4l2_subdev *sd = i2c_get_clientdata(client); in saa717x_remove() local
1330 v4l2_device_unregister_subdev(sd); in saa717x_remove()
1331 v4l2_ctrl_handler_free(sd->ctrl_handler); in saa717x_remove()
1334 /* ----------------------------------------------------------------------- */