Commit fa3e7036 authored by Andy Walls's avatar Andy Walls Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (10757): cx18, v4l2-chip-ident: Finish conversion of AV decoder core to v4l2_subdev



Added a new chip identifer to v4l2-chip-ident for the integrated A/V broadcast
decoder core internal to the CX23418.  Completed separation and encapsulation
of the A/V decoder core interface as a v4l2_subdevice.  The cx18 driver now
compiles and links again.

Signed-off-by: default avatarAndy Walls <awalls@radix.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5811cf99
Loading
Loading
Loading
Loading
+62 −23
Original line number Diff line number Diff line
@@ -201,16 +201,46 @@ 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);

	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;
	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);

	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);
	*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);
}
+7 −3
Original line number Diff line number Diff line
@@ -323,6 +323,11 @@ static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd)
	return container_of(sd, struct cx18_av_state, sd);
}

enum cx18_av_subdev_init_arg {
	CX18_AV_INIT_NORMAL = 0,
	CX18_AV_INIT_PLLS = 1,
};

/* ----------------------------------------------------------------------- */
/* cx18_av-core.c 							   */
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
@@ -337,9 +342,8 @@ int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
void cx18_av_std_setup(struct cx18 *cx);

int cx18_av_cmd(struct cx18 *cx, int cmd, void *arg); /* FIXME - Remove */
int cx18_av_init(struct cx18 *cx);
void cx18_av_fini(struct cx18 *cx);
int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd);
void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd);

/* ----------------------------------------------------------------------- */
/* cx18_av-firmware.c                                                      */
+4 −4
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
	case V4L2_CID_HUE:
	case V4L2_CID_SATURATION:
	case V4L2_CID_CONTRAST:
		if (cx18_av_cmd(cx, VIDIOC_QUERYCTRL, qctrl))
		if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl))
			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
		return 0;

@@ -126,7 +126,7 @@ static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
	case V4L2_CID_HUE:
	case V4L2_CID_SATURATION:
	case V4L2_CID_CONTRAST:
		return cx18_av_cmd(cx, VIDIOC_S_CTRL, vctrl);
		return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl);

	case V4L2_CID_AUDIO_VOLUME:
	case V4L2_CID_AUDIO_MUTE:
@@ -151,7 +151,7 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
	case V4L2_CID_HUE:
	case V4L2_CID_SATURATION:
	case V4L2_CID_CONTRAST:
		return cx18_av_cmd(cx, VIDIOC_G_CTRL, vctrl);
		return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl);

	case V4L2_CID_AUDIO_VOLUME:
	case V4L2_CID_AUDIO_MUTE:
@@ -278,7 +278,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
			fmt.fmt.pix.width = cx->params.width
						/ (is_mpeg1 ? 2 : 1);
			fmt.fmt.pix.height = cx->params.height;
			cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt);
			v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt);
		}
		priv.cx = cx;
		priv.s = &cx->streams[id->type];
+11 −7
Original line number Diff line number Diff line
@@ -621,13 +621,6 @@ static void __devinit cx18_init_struct2(struct cx18 *cx)
		i = 0;
	cx->active_input = i;
	cx->audio_input = cx->card->video_inputs[i].audio_index;
	cx->av_state.vid_input = CX18_AV_COMPOSITE7;
	cx->av_state.aud_input = CX18_AV_AUDIO8;
	cx->av_state.audclk_freq = 48000;
	cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
	cx->av_state.slicer_line_delay = 0;
	cx->av_state.slicer_line_offset =
		(10 + cx->av_state.slicer_line_delay - 2);
}

static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
@@ -812,6 +805,14 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,

	cx18_gpio_init(cx);

	retval = cx18_av_probe(cx, &cx->sd_av);
	if (retval) {
		CX18_ERR("Could not register A/V decoder subdevice\n");
		goto free_map;
	}
	/* Initialize the A/V decoder PLLs to sane defaults */
	v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_PLLS);

	/* active i2c  */
	CX18_DEBUG_INFO("activating i2c...\n");
	retval = init_cx18_i2c(cx);
@@ -1020,6 +1021,9 @@ int cx18_init_on_first_open(struct cx18 *cx)
	cx18_vapi(cx, CX18_APU_RESETAI, 0);
	cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);

	/* Init the A/V decoder, if it hasn't been already */
	v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_NORMAL);

	vf.tuner = 0;
	vf.type = V4L2_TUNER_ANALOG_TV;
	vf.frequency = 6400; /* the tuner 'baseline' frequency */
+1 −0
Original line number Diff line number Diff line
@@ -448,6 +448,7 @@ struct cx18 {
	int instance;
	struct pci_dev *pci_dev;
	struct v4l2_device v4l2_dev;
	struct v4l2_subdev *sd_av;

	const struct cx18_card *card;	/* card information */
	const char *card_name;  /* full name of the card */
Loading