V4L/DVB (11369): v4l2-subdev: add load_fw and use that instead of abusing core->init.
The init callback was used in several places to load firmware. Make a separate load_fw callback for that. This makes the code a lot more understandable. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
7c9fc9d50f
commit
cc26b076cf
@ -202,44 +202,43 @@ static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
|
||||
}
|
||||
|
||||
static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
|
||||
{
|
||||
struct cx18 *cx = v4l2_get_subdevdata(sd);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx18_av_load_fw(struct v4l2_subdev *sd)
|
||||
{
|
||||
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;
|
||||
if (!state->is_initialized) {
|
||||
/* initialize on first use */
|
||||
state->is_initialized = 1;
|
||||
cx18_av_initialize(cx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1185,6 +1184,7 @@ 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,
|
||||
.load_fw = cx18_av_load_fw,
|
||||
.reset = cx18_av_reset,
|
||||
.queryctrl = cx18_av_queryctrl,
|
||||
.g_ctrl = cx18_av_g_ctrl,
|
||||
|
@ -328,11 +328,6 @@ 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);
|
||||
|
@ -810,7 +810,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
|
||||
CX18_ERR("Could not register A/V decoder subdevice\n");
|
||||
goto free_map;
|
||||
}
|
||||
cx18_call_hw(cx, CX18_HW_418_AV, core, init, (u32) CX18_AV_INIT_PLLS);
|
||||
cx18_call_hw(cx, CX18_HW_418_AV, core, init, 0);
|
||||
|
||||
/* Initialize GPIO Reset Controller to do chip resets during i2c init */
|
||||
if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
|
||||
@ -1028,7 +1028,7 @@ int cx18_init_on_first_open(struct cx18 *cx)
|
||||
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);
|
||||
v4l2_subdev_call(cx->sd_av, core, load_fw);
|
||||
|
||||
vf.tuner = 0;
|
||||
vf.type = V4L2_TUNER_ANALOG_TV;
|
||||
|
@ -316,7 +316,7 @@ void cx231xx_card_setup(struct cx231xx *dev)
|
||||
"cx25840", "cx25840", 0x88 >> 1);
|
||||
if (dev->sd_cx25840 == NULL)
|
||||
cx231xx_info("cx25840 subdev registration failure\n");
|
||||
cx25840_call(dev, core, init, 0);
|
||||
cx25840_call(dev, core, load_fw);
|
||||
|
||||
}
|
||||
|
||||
|
@ -741,7 +741,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
|
||||
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap,
|
||||
"cx25840", "cx25840", 0x88 >> 1);
|
||||
v4l2_subdev_call(dev->sd_cx25840, core, init, 0);
|
||||
v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1182,7 @@ static void log_audio_status(struct i2c_client *client)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/* This init operation must be called to load the driver's firmware.
|
||||
/* This load_fw operation must be called to load the driver's firmware.
|
||||
Without this the audio standard detection will fail and you will
|
||||
only get mono.
|
||||
|
||||
@ -1192,13 +1192,13 @@ static void log_audio_status(struct i2c_client *client)
|
||||
postponing it is that loading this firmware takes a long time (seconds)
|
||||
due to the slow i2c bus speed. So it will speed up the boot process if
|
||||
you can avoid loading the fw as long as the video device isn't used. */
|
||||
static int cx25840_init(struct v4l2_subdev *sd, u32 val)
|
||||
static int cx25840_load_fw(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct cx25840_state *state = to_state(sd);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
if (!state->is_initialized) {
|
||||
/* initialize on first use */
|
||||
/* initialize and load firmware */
|
||||
state->is_initialized = 1;
|
||||
if (state->is_cx25836)
|
||||
cx25836_initialize(client);
|
||||
@ -1473,7 +1473,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = {
|
||||
.s_ctrl = cx25840_s_ctrl,
|
||||
.queryctrl = cx25840_queryctrl,
|
||||
.reset = cx25840_reset,
|
||||
.init = cx25840_init,
|
||||
.load_fw = cx25840_load_fw,
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = cx25840_g_register,
|
||||
.s_register = cx25840_s_register,
|
||||
|
@ -1234,7 +1234,7 @@ int ivtv_init_on_first_open(struct ivtv *itv)
|
||||
if (itv->card->hw_all & IVTV_HW_CX25840) {
|
||||
struct v4l2_control ctrl;
|
||||
|
||||
v4l2_subdev_call(itv->sd_video, core, init, 0);
|
||||
v4l2_subdev_call(itv->sd_video, core, load_fw);
|
||||
/* CX25840_CID_ENABLE_PVR150_WORKAROUND */
|
||||
ctrl.id = V4L2_CID_PRIVATE_BASE;
|
||||
ctrl.value = itv->pvr150_workaround;
|
||||
|
@ -2185,7 +2185,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
|
||||
pvr2_hdw_load_modules(hdw);
|
||||
if (!pvr2_hdw_dev_ok(hdw)) return;
|
||||
|
||||
v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0);
|
||||
v4l2_device_call_all(&hdw->v4l2_dev, 0, core, load_fw);
|
||||
|
||||
for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
|
||||
cptr = hdw->controls + idx;
|
||||
|
@ -89,7 +89,9 @@ struct v4l2_crystal_freq {
|
||||
values. Do not use for new drivers and should be removed in existing
|
||||
drivers.
|
||||
|
||||
reset: generic reset command. The argument selects which subsystems to
|
||||
load_fw: load firmware.
|
||||
|
||||
reset: generic reset command. The argument selects which subsystems to
|
||||
reset. Passing 0 will always reset the whole chip. Do not use for new
|
||||
drivers without discussing this first on the linux-media mailinglist.
|
||||
There should be no reason normally to reset a device.
|
||||
@ -101,6 +103,7 @@ struct v4l2_subdev_core_ops {
|
||||
int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
|
||||
int (*log_status)(struct v4l2_subdev *sd);
|
||||
int (*init)(struct v4l2_subdev *sd, u32 val);
|
||||
int (*load_fw)(struct v4l2_subdev *sd);
|
||||
int (*reset)(struct v4l2_subdev *sd, u32 val);
|
||||
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
|
||||
int (*queryctrl)(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);
|
||||
@ -175,31 +178,31 @@ struct v4l2_subdev_audio_ops {
|
||||
v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the
|
||||
type field is set to 0 on return.
|
||||
|
||||
s_vbi_data: used to generate VBI signals on a video signal.
|
||||
s_vbi_data: used to generate VBI signals on a video signal.
|
||||
v4l2_sliced_vbi_data is filled with the data packets that should be
|
||||
output. Note that if you set the line field to 0, then that VBI signal
|
||||
is disabled. If no valid VBI data was found, then the type field is
|
||||
set to 0 on return.
|
||||
|
||||
g_vbi_data: used to obtain the sliced VBI packet from a readback register.
|
||||
g_vbi_data: used to obtain the sliced VBI packet from a readback register.
|
||||
Not all video decoders support this. If no data is available because
|
||||
the readback register contains invalid or erroneous data -EIO is
|
||||
returned. Note that you must fill in the 'id' member and the 'field'
|
||||
member (to determine whether CC data from the first or second field
|
||||
should be obtained).
|
||||
|
||||
s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
|
||||
s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
|
||||
video input devices.
|
||||
|
||||
s_crystal_freq: sets the frequency of the crystal used to generate the
|
||||
s_crystal_freq: sets the frequency of the crystal used to generate the
|
||||
clocks. An extra flags field allows device specific configuration
|
||||
regarding clock frequency dividers, etc. If not used, then set flags
|
||||
to 0. If the frequency is not supported, then -EINVAL is returned.
|
||||
|
||||
g_input_status: get input status. Same as the status field in the v4l2_input
|
||||
g_input_status: get input status. Same as the status field in the v4l2_input
|
||||
struct.
|
||||
|
||||
s_routing: see s_routing in audio_ops, except this version is for video
|
||||
s_routing: see s_routing in audio_ops, except this version is for video
|
||||
devices.
|
||||
*/
|
||||
struct v4l2_subdev_video_ops {
|
||||
|
Loading…
Reference in New Issue
Block a user