diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-av-core.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 85 |
1 files changed, 62 insertions, 23 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 9b30f77..f9bb77a 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -201,15 +201,45 @@ static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) return 0; } -static int cx18_av_init_hardware(struct v4l2_subdev *sd, u32 val) +static int cx18_av_init(struct v4l2_subdev *sd, u32 val) { struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - if (!state->is_initialized) { - /* initialize on first use */ - state->is_initialized = 1; - cx18_av_initialize(cx); + switch (val) { + case CX18_AV_INIT_PLLS: + /* + * The crystal freq used in calculations in this driver will be + * 28.636360 MHz. + * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. + */ + + /* + * VDCLK Integer = 0x0f, Post Divider = 0x04 + * AIMCLK Integer = 0x0e, Post Divider = 0x16 + */ + cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); + + /* VDCLK Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ + cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); + + /* AIMCLK Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ + cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); + + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + break; + + case CX18_AV_INIT_NORMAL: + default: + if (!state->is_initialized) { + /* initialize on first use */ + state->is_initialized = 1; + cx18_av_initialize(cx); + } + break; } return 0; } @@ -1095,14 +1125,11 @@ static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match) static int cx18_av_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { + struct cx18_av_state *state = to_cx18_av_state(sd); + if (cx18_av_dbg_match(&chip->match)) { - /* - * Nothing else is going to claim to be this combination, - * and the real host chip revision will be returned by a host - * match on address 0. - */ - chip->ident = V4L2_IDENT_CX25843; - chip->revision = V4L2_IDENT_CX23418; /* Why not */ + chip->ident = state->id; + chip->revision = state->rev; } return 0; } @@ -1143,7 +1170,7 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, static const struct v4l2_subdev_core_ops cx18_av_general_ops = { .g_chip_ident = cx18_av_g_chip_ident, .log_status = cx18_av_log_status, - .init = cx18_av_init_hardware, + .init = cx18_av_init, .reset = cx18_av_reset, .queryctrl = cx18_av_queryctrl, .g_ctrl = cx18_av_g_ctrl, @@ -1182,19 +1209,31 @@ static const struct v4l2_subdev_ops cx18_av_ops = { .video = &cx18_av_video_ops, }; -int cx18_av_init(struct cx18 *cx) +int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd) { - struct v4l2_subdev *sd = &cx->av_state.sd; - - v4l2_subdev_init(sd, &cx18_av_ops); - v4l2_set_subdevdata(sd, cx); - snprintf(sd->name, sizeof(sd->name), - "%s-internal A/V decoder", cx->v4l2_dev.name); - sd->grp_id = CX18_HW_CX23418; - return v4l2_device_register_subdev(&cx->v4l2_dev, sd); + struct cx18_av_state *state = &cx->av_state; + + state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; + state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) + ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN; + + state->vid_input = CX18_AV_COMPOSITE7; + state->aud_input = CX18_AV_AUDIO8; + state->audclk_freq = 48000; + state->audmode = V4L2_TUNER_MODE_LANG1; + state->slicer_line_delay = 0; + state->slicer_line_offset = (10 + state->slicer_line_delay - 2); + + *sd = &state->sd; + v4l2_subdev_init(*sd, &cx18_av_ops); + v4l2_set_subdevdata(*sd, cx); + snprintf((*sd)->name, sizeof((*sd)->name), + "%s internal A/V decoder", cx->v4l2_dev.name); + (*sd)->grp_id = CX18_HW_CX23418; + return v4l2_device_register_subdev(&cx->v4l2_dev, *sd); } -void cx18_av_fini(struct cx18 *cx) +void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd) { v4l2_device_unregister_subdev(&cx->av_state.sd); } |