Lines Matching +full:1 +full:- +full:sd
2 * ths8200 - Texas Instruments THS8200 video encoder driver
23 #include <linux/v4l2-dv-timings.h>
25 #include <media/v4l2-dv-timings.h>
26 #include <media/v4l2-async.h>
27 #include <media/v4l2-device.h>
33 MODULE_PARM_DESC(debug, "debug level (0-2)");
41 struct v4l2_subdev sd; member
56 static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) in to_state() argument
58 return container_of(sd, struct ths8200_state, sd); in to_state()
71 static int ths8200_read(struct v4l2_subdev *sd, u8 reg) in ths8200_read() argument
73 struct i2c_client *client = v4l2_get_subdevdata(sd); in ths8200_read()
78 static int ths8200_write(struct v4l2_subdev *sd, u8 reg, u8 val) in ths8200_write() argument
80 struct i2c_client *client = v4l2_get_subdevdata(sd); in ths8200_write()
89 v4l2_err(sd, "I2C Write Problem\n"); in ths8200_write()
93 /* To set specific bits in the register, a clear-mask is given (to be AND-ed),
94 * and then the value-mask (to be OR-ed).
97 ths8200_write_and_or(struct v4l2_subdev *sd, u8 reg, in ths8200_write_and_or() argument
100 ths8200_write(sd, reg, (ths8200_read(sd, reg) & clr_mask) | val_mask); in ths8200_write_and_or()
105 static int ths8200_g_register(struct v4l2_subdev *sd, in ths8200_g_register() argument
108 reg->val = ths8200_read(sd, reg->reg & 0xff); in ths8200_g_register()
109 reg->size = 1; in ths8200_g_register()
114 static int ths8200_s_register(struct v4l2_subdev *sd, in ths8200_s_register() argument
117 ths8200_write(sd, reg->reg & 0xff, reg->val & 0xff); in ths8200_s_register()
123 static int ths8200_log_status(struct v4l2_subdev *sd) in ths8200_log_status() argument
125 struct ths8200_state *state = to_state(sd); in ths8200_log_status()
126 uint8_t reg_03 = ths8200_read(sd, THS8200_CHIP_CTL); in ths8200_log_status()
128 v4l2_info(sd, "----- Chip status -----\n"); in ths8200_log_status()
129 v4l2_info(sd, "version: %u\n", state->chip_version); in ths8200_log_status()
130 v4l2_info(sd, "power: %s\n", (reg_03 & 0x0c) ? "off" : "on"); in ths8200_log_status()
131 v4l2_info(sd, "reset: %s\n", (reg_03 & 0x01) ? "off" : "on"); in ths8200_log_status()
132 v4l2_info(sd, "test pattern: %s\n", in ths8200_log_status()
134 v4l2_info(sd, "format: %ux%u\n", in ths8200_log_status()
135 ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_MSB) * 256 + in ths8200_log_status()
136 ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), in ths8200_log_status()
137 (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + in ths8200_log_status()
138 ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); in ths8200_log_status()
139 v4l2_print_dv_timings(sd->name, "Configured format:", in ths8200_log_status()
140 &state->dv_timings, true); in ths8200_log_status()
145 static int ths8200_s_power(struct v4l2_subdev *sd, int on) in ths8200_s_power() argument
147 struct ths8200_state *state = to_state(sd); in ths8200_s_power()
149 v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); in ths8200_s_power()
151 state->power_on = on; in ths8200_s_power()
153 /* Power up/down - leave in reset state until input video is present */ in ths8200_s_power()
154 ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0xf2, (on ? 0x00 : 0x0c)); in ths8200_s_power()
168 /* -----------------------------------------------------------------------------
172 static int ths8200_s_stream(struct v4l2_subdev *sd, int enable) in ths8200_s_stream() argument
174 struct ths8200_state *state = to_state(sd); in ths8200_s_stream()
176 if (enable && !state->power_on) in ths8200_s_stream()
177 ths8200_s_power(sd, true); in ths8200_s_stream()
179 ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0xfe, in ths8200_s_stream()
182 v4l2_dbg(1, debug, sd, "%s: %sable\n", in ths8200_s_stream()
188 static void ths8200_core_init(struct v4l2_subdev *sd) in ths8200_core_init() argument
191 ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0x3f, 0xc0); in ths8200_core_init()
195 * bypass 422-444 interpolation, in ths8200_core_init()
198 ths8200_write(sd, THS8200_DATA_CNTL, 0x70); in ths8200_core_init()
203 ths8200_write(sd, THS8200_DTG1_MODE, 0x87); in ths8200_core_init()
205 /**** Display Timing Generator Control, Part 1 (DTG1). ****/ in ths8200_core_init()
210 ths8200_write(sd, THS8200_DTG1_Y_SYNC_MSB, 0x00); in ths8200_core_init()
211 ths8200_write(sd, THS8200_DTG1_CBCR_SYNC_MSB, 0x00); in ths8200_core_init()
214 static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt) in ths8200_setup() argument
217 uint16_t line_start_active_video = (bt->vsync + bt->vbackporch); in ths8200_setup()
218 uint16_t line_start_front_porch = (vtotal(bt) - bt->vfrontporch); in ths8200_setup()
222 ths8200_s_stream(sd, false); in ths8200_setup()
225 ths8200_write(sd, THS8200_DTG1_SPEC_A, bt->hsync); in ths8200_setup()
226 ths8200_write(sd, THS8200_DTG1_SPEC_B, bt->hfrontporch); in ths8200_setup()
229 if (!bt->interlaced) in ths8200_setup()
230 ths8200_write(sd, THS8200_DTG1_SPEC_C, 0x00); in ths8200_setup()
235 ths8200_write(sd, THS8200_DTG1_SPEC_D_LSB, in ths8200_setup()
236 (bt->hbackporch + bt->hsync) & 0xff); in ths8200_setup()
237 /* Zero for SDTV-mode. MSB in 0x2b */ in ths8200_setup()
238 ths8200_write(sd, THS8200_DTG1_SPEC_E_LSB, 0x00); in ths8200_setup()
243 ths8200_write(sd, THS8200_DTG1_SPEC_DEH_MSB, in ths8200_setup()
244 ((bt->hbackporch + bt->hsync) & 0x100) >> 1); in ths8200_setup()
247 ths8200_write(sd, THS8200_DTG1_SPEC_K_LSB, (bt->hfrontporch) & 0xff); in ths8200_setup()
248 ths8200_write(sd, THS8200_DTG1_SPEC_K_MSB, in ths8200_setup()
249 ((bt->hfrontporch) & 0x700) >> 8); in ths8200_setup()
252 ths8200_write(sd, THS8200_DTG1_SPEC_G_LSB, (htotal(bt)/2) & 0xff); in ths8200_setup()
253 ths8200_write(sd, THS8200_DTG1_SPEC_G_MSB, in ths8200_setup()
257 ths8200_write(sd, THS8200_DTG1_TOT_PIXELS_MSB, htotal(bt) >> 8); in ths8200_setup()
258 ths8200_write(sd, THS8200_DTG1_TOT_PIXELS_LSB, htotal(bt) & 0xff); in ths8200_setup()
264 ths8200_write(sd, THS8200_DTG1_FRAME_FIELD_SZ_MSB, in ths8200_setup()
266 ths8200_write(sd, THS8200_DTG1_FRAME_SZ_LSB, vtotal(bt) & 0xff); in ths8200_setup()
271 if (!bt->interlaced) in ths8200_setup()
272 ths8200_write(sd, THS8200_DTG1_FIELD_SZ_LSB, 0xff); in ths8200_setup()
277 * that sets all the RGB-outputs to zero is used in the blanking areas, in ths8200_setup()
278 * while a line type that enable the RGB-outputs is used in active video in ths8200_setup()
284 * 0x9 - Full normal sync pulse: Blocks data when dtg1_pass is off. in ths8200_setup()
286 * 0x0 - Active video: Video data is always passed. Used in active in ths8200_setup()
289 ths8200_write_and_or(sd, THS8200_DTG2_BP1_2_MSB, 0x88, in ths8200_setup()
292 ths8200_write(sd, THS8200_DTG2_BP3_4_MSB, ((vtotal(bt)) >> 4) & 0x70); in ths8200_setup()
293 ths8200_write(sd, THS8200_DTG2_BP1_LSB, line_start_active_video & 0xff); in ths8200_setup()
294 ths8200_write(sd, THS8200_DTG2_BP2_LSB, line_start_front_porch & 0xff); in ths8200_setup()
295 ths8200_write(sd, THS8200_DTG2_BP3_LSB, (vtotal(bt)) & 0xff); in ths8200_setup()
298 ths8200_write(sd, THS8200_DTG2_LINETYPE1, 0x90); in ths8200_setup()
299 ths8200_write(sd, THS8200_DTG2_LINETYPE2, 0x90); in ths8200_setup()
302 ths8200_write(sd, THS8200_DTG2_HLENGTH_LSB, bt->hsync & 0xff); in ths8200_setup()
303 ths8200_write_and_or(sd, THS8200_DTG2_HLENGTH_LSB_HDLY_MSB, 0x3f, in ths8200_setup()
304 (bt->hsync >> 2) & 0xc0); in ths8200_setup()
307 ths8200_write_and_or(sd, THS8200_DTG2_HLENGTH_LSB_HDLY_MSB, 0xe0, in ths8200_setup()
309 ths8200_write(sd, THS8200_DTG2_HLENGTH_HDLY_LSB, htotal(bt)); in ths8200_setup()
311 /* v sync width transmitted (must add 1 to get correct output) */ in ths8200_setup()
312 ths8200_write(sd, THS8200_DTG2_VLENGTH1_LSB, (bt->vsync + 1) & 0xff); in ths8200_setup()
313 ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0x3f, in ths8200_setup()
314 ((bt->vsync + 1) >> 2) & 0xc0); in ths8200_setup()
316 /* The pixel value v sync is asserted on (must add 1 to get correct output) */ in ths8200_setup()
317 ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0xf8, in ths8200_setup()
318 ((vtotal(bt) + 1) >> 8) & 0x7); in ths8200_setup()
319 ths8200_write(sd, THS8200_DTG2_VDLY1_LSB, vtotal(bt) + 1); in ths8200_setup()
322 * be set to all 1. in ths8200_setup()
324 ths8200_write(sd, THS8200_DTG2_VLENGTH2_LSB, 0x00); in ths8200_setup()
325 ths8200_write(sd, THS8200_DTG2_VLENGTH2_MSB_VDLY2_MSB, 0x07); in ths8200_setup()
326 ths8200_write(sd, THS8200_DTG2_VDLY2_LSB, 0xff); in ths8200_setup()
330 ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_MSB, 0); in ths8200_setup()
331 ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_LSB, 0); in ths8200_setup()
332 ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_MSB, 0); in ths8200_setup()
333 ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_LSB, 0); in ths8200_setup()
336 if (bt->polarities & V4L2_DV_HSYNC_POS_POL) { in ths8200_setup()
340 if (bt->polarities & V4L2_DV_VSYNC_POS_POL) { in ths8200_setup()
349 ths8200_write(sd, THS8200_DTG2_CNTL, 0x44 | polarity); in ths8200_setup()
352 ths8200_s_stream(sd, true); in ths8200_setup()
354 v4l2_dbg(1, debug, sd, "%s: frame %dx%d, polarity %d\n" in ths8200_setup()
357 polarity, bt->hfrontporch, bt->hbackporch, in ths8200_setup()
358 bt->hsync, bt->vsync); in ths8200_setup()
361 static int ths8200_s_dv_timings(struct v4l2_subdev *sd, unsigned int pad, in ths8200_s_dv_timings() argument
364 struct ths8200_state *state = to_state(sd); in ths8200_s_dv_timings()
366 v4l2_dbg(1, debug, sd, "%s:\n", __func__); in ths8200_s_dv_timings()
369 return -EINVAL; in ths8200_s_dv_timings()
373 return -EINVAL; in ths8200_s_dv_timings()
377 v4l2_dbg(1, debug, sd, "Unsupported format\n"); in ths8200_s_dv_timings()
378 return -EINVAL; in ths8200_s_dv_timings()
381 timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; in ths8200_s_dv_timings()
384 state->dv_timings = *timings; in ths8200_s_dv_timings()
386 ths8200_setup(sd, &timings->bt); in ths8200_s_dv_timings()
391 static int ths8200_g_dv_timings(struct v4l2_subdev *sd, unsigned int pad, in ths8200_g_dv_timings() argument
394 struct ths8200_state *state = to_state(sd); in ths8200_g_dv_timings()
396 v4l2_dbg(1, debug, sd, "%s:\n", __func__); in ths8200_g_dv_timings()
399 return -EINVAL; in ths8200_g_dv_timings()
401 *timings = state->dv_timings; in ths8200_g_dv_timings()
406 static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, in ths8200_enum_dv_timings() argument
409 if (timings->pad != 0) in ths8200_enum_dv_timings()
410 return -EINVAL; in ths8200_enum_dv_timings()
416 static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, in ths8200_dv_timings_cap() argument
419 if (cap->pad != 0) in ths8200_dv_timings_cap()
420 return -EINVAL; in ths8200_dv_timings_cap()
448 struct v4l2_subdev *sd; in ths8200_probe() local
452 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) in ths8200_probe()
453 return -EIO; in ths8200_probe()
455 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); in ths8200_probe()
457 return -ENOMEM; in ths8200_probe()
459 sd = &state->sd; in ths8200_probe()
460 v4l2_i2c_subdev_init(sd, client, &ths8200_ops); in ths8200_probe()
462 state->chip_version = ths8200_read(sd, THS8200_VERSION); in ths8200_probe()
463 v4l2_dbg(1, debug, sd, "chip version 0x%x\n", state->chip_version); in ths8200_probe()
465 ths8200_core_init(sd); in ths8200_probe()
467 error = v4l2_async_register_subdev(&state->sd); in ths8200_probe()
471 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, in ths8200_probe()
472 client->addr << 1, client->adapter->name); in ths8200_probe()
479 struct v4l2_subdev *sd = i2c_get_clientdata(client); in ths8200_remove() local
480 struct ths8200_state *decoder = to_state(sd); in ths8200_remove()
482 v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, in ths8200_remove()
483 client->addr << 1, client->adapter->name); in ths8200_remove()
485 ths8200_s_power(sd, false); in ths8200_remove()
486 v4l2_async_unregister_subdev(&decoder->sd); in ths8200_remove()