mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull second set of media updates from Mauro Carvalho Chehab:
"Despite its size, most of the stuff here is trivial. This series
contains:
- s5p-mfc: additions at the driver and at the core to support H.264
hardware codec;
- Some improvements at s5p and davinci embedded drivers;
- Some V4L2 compliance fixes applied on a few drivers;
- Several random trivial patches, including several fixes and a few
new board support additions;
Notes:
1) Some Exynos media patches were dependent on some -arm fixes that
got merged on changeset 782cd9e. That's why this pull request is
based that changeset.
2) As promised, I reviewed the pending VB2 DMABUF series.
While setting a test environment, it was noticed that the upstream
support for Samsung Exynos 4 boards (smdk310 and Origen) are
broken upstream, likely due to regressions: both defconfigs are
wrong and regulator settings for both boards are broken. That,
allied with some bug at the dummy regulator driver, causes OOPSes
during boot time.
Long story short: even fixing the above, the proposed patches
OOPSed when running the DMABUF test. Not sure yet if the OOPSes
are due to some other undetected regressions, or due to some bug
on the patches.
Due to the above, DMABUF patches for vb2 got NACKed for 3.7."
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (109 commits)
[media] m5mols: Add missing #include <linux/sizes.h>
[media] stk1160: Add support for S-Video input
Revert "[media] omap3isp: Replace cpu_is_omap3630() with ISP revision check"
[media] dvb: LNA implementation changes
[media] v4l2-ioctl: fix W=1 warnings
[media] v4l2-ioctl: add blocks check for VIDIOC_SUBDEV_G/S_EDID
[media] omap3isp: Fix compilation error in ispreg.h
[media] rc-msi-digivox-ii: Add full scan keycodes
[media] cx25821: testing the wrong variable
[media] tda18271-common: hold the I2C adapter during write transfers
[media] ds3000: add module parameter to force firmware upload
[media] drivers/media: Remove unnecessary semicolon
[media] winbond: remove space from driver name
[media] iguanair: cannot send data from the stack
[media] omap3isp: Replace cpu_is_omap3630() with ISP revision check
[media] dvb-usb: print small buffers via %*ph
[media] uvc: Add return code check at vb2_queue_init()
[media] em28xx: Replace memcpy with struct assignment
[media] bt8xx: Add video4linux control V4L2_CID_COLOR_KILLER
[media] mem2mem_testdev: Use devm_kzalloc() in probe
...
Conflicts:
arch/arm/mach-davinci/include/mach/da8xx.h
This commit is contained in:
commit
4f1cd91497
170 changed files with 8074 additions and 3212 deletions
|
|
@ -966,6 +966,8 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
|
|||
break;
|
||||
}
|
||||
|
||||
c->lna = LNA_AUTO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1054,6 +1056,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
|
|||
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
|
||||
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
|
||||
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
|
||||
|
||||
_DTV_CMD(DTV_LNA, 0, 0),
|
||||
};
|
||||
|
||||
static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
|
||||
|
|
@ -1440,6 +1444,10 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
|||
tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d;
|
||||
break;
|
||||
|
||||
case DTV_LNA:
|
||||
tvp->u.data = c->lna;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1731,10 +1739,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
|||
case DTV_INTERLEAVING:
|
||||
c->interleaving = tvp->u.data;
|
||||
break;
|
||||
case DTV_LNA:
|
||||
if (fe->ops.set_lna)
|
||||
r = fe->ops.set_lna(fe, tvp->u.data);
|
||||
break;
|
||||
|
||||
/* ISDB-T Support here */
|
||||
case DTV_ISDBT_PARTIAL_RECEPTION:
|
||||
|
|
@ -1806,6 +1810,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
|||
fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
|
||||
break;
|
||||
|
||||
case DTV_LNA:
|
||||
c->lna = tvp->u.data;
|
||||
if (fe->ops.set_lna)
|
||||
r = fe->ops.set_lna(fe);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -2309,7 +2319,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
fepriv->tune_mode_flags = (unsigned long) parg;
|
||||
err = 0;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ struct dvb_frontend_ops {
|
|||
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
|
||||
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
|
||||
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
|
||||
int (*set_lna)(struct dvb_frontend *, int);
|
||||
int (*set_lna)(struct dvb_frontend *);
|
||||
|
||||
/* These callbacks are for devices that implement their own
|
||||
* tuning algorithms, rather than a simple swzigzag
|
||||
|
|
@ -391,6 +391,8 @@ struct dtv_frontend_properties {
|
|||
u8 atscmh_sccc_code_mode_b;
|
||||
u8 atscmh_sccc_code_mode_c;
|
||||
u8 atscmh_sccc_code_mode_d;
|
||||
|
||||
u32 lna;
|
||||
};
|
||||
|
||||
struct dvb_frontend {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
|
|||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
};
|
||||
}
|
||||
|
||||
ret = a8293_wr(priv, &priv->reg[0], 1);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
|
|||
KBUILD_MODNAME, gpio);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
};
|
||||
}
|
||||
|
||||
switch (gpio) {
|
||||
case 0:
|
||||
|
|
@ -253,7 +253,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
|
|||
default:
|
||||
pos = 4;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
|
||||
if (ret)
|
||||
|
|
@ -726,7 +726,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
|
|||
default:
|
||||
dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__);
|
||||
auto_mode = 1;
|
||||
};
|
||||
}
|
||||
|
||||
switch (c->modulation) {
|
||||
case QAM_AUTO:
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
|
|||
{
|
||||
struct af9033_state *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret, i, spec_inv;
|
||||
int ret, i, spec_inv, sampling_freq;
|
||||
u8 tmp, buf[3], bandwidth_reg_val;
|
||||
u32 if_frequency, freq_cw, adc_freq;
|
||||
|
||||
|
|
@ -465,18 +465,20 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
|
|||
else
|
||||
if_frequency = 0;
|
||||
|
||||
while (if_frequency > (adc_freq / 2))
|
||||
if_frequency -= adc_freq;
|
||||
sampling_freq = if_frequency;
|
||||
|
||||
if (if_frequency >= 0)
|
||||
while (sampling_freq > (adc_freq / 2))
|
||||
sampling_freq -= adc_freq;
|
||||
|
||||
if (sampling_freq >= 0)
|
||||
spec_inv *= -1;
|
||||
else
|
||||
if_frequency *= -1;
|
||||
sampling_freq *= -1;
|
||||
|
||||
freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul);
|
||||
freq_cw = af9033_div(state, sampling_freq, adc_freq, 23ul);
|
||||
|
||||
if (spec_inv == -1)
|
||||
freq_cw *= -1;
|
||||
freq_cw = 0x800000 - freq_cw;
|
||||
|
||||
/* get adc multiplies */
|
||||
ret = af9033_rd_reg(state, 0x800045, &tmp);
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ static int bcm3510_set_frontend(struct dvb_frontend *fe)
|
|||
cmd.ACQUIRE1.IF_FREQ = 0x0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
cmd.ACQUIRE0.OFFSET = 0;
|
||||
cmd.ACQUIRE0.NTSCSWEEP = 1;
|
||||
cmd.ACQUIRE0.FA = 1;
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
|
|||
} else
|
||||
return -EOPNOTSUPP;
|
||||
/* fixme (low): which is the correct return code? */
|
||||
};
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
|
|||
cx24110_writereg(state,0x07,tmp|0x3);
|
||||
cx24110_writereg(state,0x06,0x78);
|
||||
fclk=90999000UL;
|
||||
};
|
||||
}
|
||||
dprintk("cx24110 debug: fclk %d Hz\n",fclk);
|
||||
/* we need to divide two integers with approx. 27 bits in 32 bit
|
||||
arithmetic giving a 25 bit result */
|
||||
|
|
@ -362,7 +362,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
|
|||
|
||||
for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
|
||||
cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -688,7 +688,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
|
|||
{
|
||||
struct cxd2820r_priv *priv;
|
||||
int ret;
|
||||
u8 tmp, gpio[GPIO_COUNT];
|
||||
u8 tmp;
|
||||
|
||||
priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
|
|
@ -735,6 +735,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
|
|||
* Use static GPIO configuration if GPIOLIB is undefined.
|
||||
* This is fallback condition.
|
||||
*/
|
||||
u8 gpio[GPIO_COUNT];
|
||||
gpio[0] = (*gpio_chip_base >> 0) & 0x07;
|
||||
gpio[1] = (*gpio_chip_base >> 3) & 0x07;
|
||||
gpio[2] = 0;
|
||||
|
|
|
|||
|
|
@ -991,7 +991,7 @@ static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult)
|
|||
if (nrRetries > DRXD_MAX_RETRIES) {
|
||||
status = -1;
|
||||
break;
|
||||
};
|
||||
}
|
||||
status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0);
|
||||
} while (waitCmd != 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "ds3000.h"
|
||||
|
||||
static int debug;
|
||||
static int force_fw_upload;
|
||||
|
||||
#define dprintk(args...) \
|
||||
do { \
|
||||
|
|
@ -392,11 +393,13 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
|
|||
|
||||
dprintk("%s()\n", __func__);
|
||||
|
||||
if (ds3000_readreg(state, 0xb2) <= 0)
|
||||
ret = ds3000_readreg(state, 0xb2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (state->skip_fw_load)
|
||||
return 0;
|
||||
if (state->skip_fw_load || !force_fw_upload)
|
||||
return 0; /* Firmware already uploaded, skipping */
|
||||
|
||||
/* Load firmware */
|
||||
/* request the firmware, this will block until someone uploads it */
|
||||
printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
|
||||
|
|
@ -1306,6 +1309,9 @@ static struct dvb_frontend_ops ds3000_ops = {
|
|||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
|
||||
|
||||
module_param(force_fw_upload, int, 0644);
|
||||
MODULE_PARM_DESC(force_fw_upload, "Force firmware upload (default:0)");
|
||||
|
||||
MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
|
||||
"DS3000/TS2020 hardware");
|
||||
MODULE_AUTHOR("Konstantin Dimitrov");
|
||||
|
|
|
|||
|
|
@ -121,16 +121,13 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
|
|||
|
||||
/* allocate memory for the internal state */
|
||||
state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
|
||||
if (state == NULL) goto error;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
|
||||
|
|
@ -141,16 +138,13 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
|
|||
|
||||
/* allocate memory for the internal state */
|
||||
state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
|
||||
if (state == NULL) goto error;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
|
||||
|
|
@ -161,16 +155,13 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
|
|||
|
||||
/* allocate memory for the internal state */
|
||||
state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
|
||||
if (state == NULL) goto error;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
}
|
||||
isl6405->config |= isl6405->override_or;
|
||||
isl6405->config &= isl6405->override_and;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
isl6421->config |= isl6421->override_or;
|
||||
isl6421->config &= isl6421->override_and;
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
|
|||
state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
|
||||
itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
|
||||
|
||||
itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
|
||||
itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */
|
||||
itd1000_write_reg(state, PLLNL, plln & 0xff);
|
||||
itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
|
||||
itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
|
||||
|
|
|
|||
|
|
@ -1421,8 +1421,8 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
|
|||
config ? config->i2c_addr : 0);
|
||||
|
||||
state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
goto fail;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
state->cfg = config;
|
||||
state->i2c_adap = i2c_adap;
|
||||
|
|
@ -1449,10 +1449,6 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
|
|||
state->frontend.dtv_property_cache.atscmh_parade_id = 1;
|
||||
|
||||
return &state->frontend;
|
||||
fail:
|
||||
lg_warn("unable to detect LG216x hardware\n");
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(lg2160_attach);
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe,
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
lnbp21->config |= lnbp21->override_or;
|
||||
lnbp21->config &= lnbp21->override_and;
|
||||
|
|
@ -108,7 +108,7 @@ static int lnbp21_set_tone(struct dvb_frontend *fe,
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
lnbp21->config |= lnbp21->override_or;
|
||||
lnbp21->config &= lnbp21->override_and;
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
|
||||
return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
|
||||
|
|
|
|||
|
|
@ -351,8 +351,8 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
|
|||
printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
|
||||
/* allocate memory for the internal state */
|
||||
state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
goto error;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
/* setup the state */
|
||||
state->config = config;
|
||||
|
|
@ -367,10 +367,6 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
|
|||
state->frontend.demodulator_priv = state;
|
||||
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(s5h1432_attach);
|
||||
|
||||
|
|
|
|||
|
|
@ -487,9 +487,9 @@ struct dvb_frontend *s921_attach(const struct s921_config *config,
|
|||
kzalloc(sizeof(struct s921_state), GFP_KERNEL);
|
||||
|
||||
dprintk("\n");
|
||||
if (state == NULL) {
|
||||
if (!state) {
|
||||
rc("Unable to kzalloc\n");
|
||||
goto rcor;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* setup the state */
|
||||
|
|
@ -502,11 +502,6 @@ struct dvb_frontend *s921_attach(const struct s921_config *config,
|
|||
state->frontend.demodulator_priv = state;
|
||||
|
||||
return &state->frontend;
|
||||
|
||||
rcor:
|
||||
kfree(state);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(s921_attach);
|
||||
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(10);
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -472,7 +472,7 @@ static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static int si21xx_init(struct dvb_frontend *fe)
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
switch (p->hierarchy) {
|
||||
case HIERARCHY_NONE:
|
||||
|
|
@ -207,7 +207,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
switch (p->code_rate_HP) {
|
||||
case FEC_1_2:
|
||||
|
|
@ -229,7 +229,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
if (known_parameters)
|
||||
*reg0xc05 |= (2 << 1); /* use specified parameters */
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
switch (p->hierarchy) {
|
||||
case HIERARCHY_NONE:
|
||||
|
|
@ -248,7 +248,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
switch (p->code_rate_HP) {
|
||||
case FEC_1_2:
|
||||
|
|
@ -270,7 +270,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
if (known_parameters)
|
||||
*reg0xc05 |= (2 << 1); /* use specified parameters */
|
||||
|
|
|
|||
|
|
@ -575,8 +575,8 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
|
|||
struct stb6100_state *state = NULL;
|
||||
|
||||
state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
goto error;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
|
@ -587,10 +587,6 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
|
|||
|
||||
printk("%s: Attaching STB6100 \n", __func__);
|
||||
return fe;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int stb6100_release(struct dvb_frontend *fe)
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(10);
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -216,7 +216,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(10);
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -387,7 +387,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
if (state->config->op0_off)
|
||||
reg0x0c &= ~0x10;
|
||||
|
|
|
|||
|
|
@ -1552,8 +1552,8 @@ static int stv0900_status(struct stv0900_internal *intp,
|
|||
bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
|
||||
* (tsbitrate1_val << 8 | tsbitrate0_val);
|
||||
bitrate /= 16384;
|
||||
dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
|
||||
};
|
||||
dprintk("TS bitrate = %d Mbit/sec\n", bitrate);
|
||||
}
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,8 +228,8 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
|
|||
struct dvb_tuner_info *info;
|
||||
|
||||
state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
goto exit;
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
|
@ -246,10 +246,6 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
|
|||
printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
|
||||
|
||||
return fe;
|
||||
|
||||
exit:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(tda665x_attach);
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
|
|||
!(tda8083_readreg(state, 0x02) & 0x80))
|
||||
{
|
||||
msleep(50);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
|
||||
|
|
@ -215,7 +215,7 @@ static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_c
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
tda8083_wait_diseqc_fifo (state, 100);
|
||||
|
||||
|
|
|
|||
|
|
@ -599,7 +599,7 @@ static void cx23885_initialize(struct i2c_client *client)
|
|||
cx25840_write4(client, 0x114, 0x01bf0c9e);
|
||||
cx25840_write4(client, 0x110, 0x000a030c);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
/* ADC2 input select */
|
||||
cx25840_write(client, 0x102, 0x10);
|
||||
|
|
|
|||
|
|
@ -16,9 +16,17 @@
|
|||
#ifndef M5MOLS_H
|
||||
#define M5MOLS_H
|
||||
|
||||
#include <linux/sizes.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include "m5mols_reg.h"
|
||||
|
||||
|
||||
/* An amount of data transmitted in addition to the value
|
||||
* determined by CAPP_JPEG_SIZE_MAX register.
|
||||
*/
|
||||
#define M5MOLS_JPEG_TAGS_SIZE 0x20000
|
||||
#define M5MOLS_MAIN_JPEG_SIZE_MAX (5 * SZ_1M)
|
||||
|
||||
extern int m5mols_debug;
|
||||
|
||||
enum m5mols_restype {
|
||||
|
|
@ -67,12 +75,14 @@ struct m5mols_exif {
|
|||
/**
|
||||
* struct m5mols_capture - Structure for the capture capability
|
||||
* @exif: EXIF information
|
||||
* @buf_size: internal JPEG frame buffer size, in bytes
|
||||
* @main: size in bytes of the main image
|
||||
* @thumb: size in bytes of the thumb image, if it was accompanied
|
||||
* @total: total size in bytes of the produced image
|
||||
*/
|
||||
struct m5mols_capture {
|
||||
struct m5mols_exif exif;
|
||||
unsigned int buf_size;
|
||||
u32 main;
|
||||
u32 thumb;
|
||||
u32 total;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ static int m5mols_capture_info(struct m5mols_info *info)
|
|||
|
||||
int m5mols_start_capture(struct m5mols_info *info)
|
||||
{
|
||||
unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE;
|
||||
struct v4l2_subdev *sd = &info->sd;
|
||||
int ret;
|
||||
|
||||
|
|
@ -120,6 +121,8 @@ int m5mols_start_capture(struct m5mols_info *info)
|
|||
ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
|
||||
if (!ret)
|
||||
ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
|
||||
if (!ret)
|
||||
ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize);
|
||||
if (!ret)
|
||||
ret = m5mols_set_mode(info, REG_CAPTURE);
|
||||
if (!ret)
|
||||
|
|
|
|||
|
|
@ -599,6 +599,51 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
|
||||
struct v4l2_mbus_frame_desc *fd)
|
||||
{
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
|
||||
if (pad != 0 || fd == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
/*
|
||||
* .get_frame_desc is only used for compressed formats,
|
||||
* thus we always return the capture frame parameters here.
|
||||
*/
|
||||
fd->entry[0].length = info->cap.buf_size;
|
||||
fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
|
||||
fd->num_entries = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
|
||||
struct v4l2_mbus_frame_desc *fd)
|
||||
{
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
|
||||
|
||||
if (pad != 0 || fd == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
|
||||
fd->num_entries = 1;
|
||||
fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
|
||||
mf->width * mf->height,
|
||||
M5MOLS_MAIN_JPEG_SIZE_MAX);
|
||||
mutex_lock(&info->lock);
|
||||
info->cap.buf_size = fd->entry[0].length;
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
|
|
@ -615,6 +660,8 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
|
|||
.enum_mbus_code = m5mols_enum_mbus_code,
|
||||
.get_fmt = m5mols_get_fmt,
|
||||
.set_fmt = m5mols_set_fmt,
|
||||
.get_frame_desc = m5mols_get_frame_desc,
|
||||
.set_frame_desc = m5mols_set_frame_desc,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@
|
|||
#define REG_JPEG 0x10
|
||||
|
||||
#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1)
|
||||
#define CAPP_JPEG_SIZE_MAX I2C_REG(CAT_CAPT_PARM, 0x0f, 4)
|
||||
#define CAPP_JPEG_RATIO I2C_REG(CAT_CAPT_PARM, 0x17, 1)
|
||||
|
||||
#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
|
||||
|
|
|
|||
|
|
@ -574,7 +574,6 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
|
|||
* V4L2 subdev control operations
|
||||
*/
|
||||
|
||||
#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
|
||||
#define V4L2_CID_BLC_AUTO (V4L2_CID_USER_BASE | 0x1002)
|
||||
#define V4L2_CID_BLC_TARGET_LEVEL (V4L2_CID_USER_BASE | 0x1003)
|
||||
#define V4L2_CID_BLC_ANALOG_OFFSET (V4L2_CID_USER_BASE | 0x1004)
|
||||
|
|
@ -739,18 +738,6 @@ static const char * const mt9p031_test_pattern_menu[] = {
|
|||
|
||||
static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
|
||||
{
|
||||
.ops = &mt9p031_ctrl_ops,
|
||||
.id = V4L2_CID_TEST_PATTERN,
|
||||
.type = V4L2_CTRL_TYPE_MENU,
|
||||
.name = "Test Pattern",
|
||||
.min = 0,
|
||||
.max = ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
|
||||
.step = 0,
|
||||
.def = 0,
|
||||
.flags = 0,
|
||||
.menu_skip_mask = 0,
|
||||
.qmenu = mt9p031_test_pattern_menu,
|
||||
}, {
|
||||
.ops = &mt9p031_ctrl_ops,
|
||||
.id = V4L2_CID_BLC_AUTO,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
|
|
@ -950,7 +937,7 @@ static int mt9p031_probe(struct i2c_client *client,
|
|||
mt9p031->model = did->driver_data;
|
||||
mt9p031->reset = -1;
|
||||
|
||||
v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
|
||||
v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6);
|
||||
|
||||
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
|
||||
|
|
@ -966,6 +953,10 @@ static int mt9p031_probe(struct i2c_client *client,
|
|||
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, pdata->target_freq,
|
||||
pdata->target_freq, 1, pdata->target_freq);
|
||||
v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||
V4L2_CID_TEST_PATTERN,
|
||||
ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0,
|
||||
0, mt9p031_test_pattern_menu);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
|
||||
v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
|
|||
* V4L2 subdev control operations
|
||||
*/
|
||||
|
||||
#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
|
||||
#define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001)
|
||||
#define V4L2_CID_BLACK_LEVEL_AUTO (V4L2_CID_USER_BASE | 0x1002)
|
||||
#define V4L2_CID_BLACK_LEVEL_OFFSET (V4L2_CID_USER_BASE | 0x1003)
|
||||
#define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
|
||||
|
|
@ -487,12 +487,11 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
ctrl->val >> 16);
|
||||
|
||||
case V4L2_CID_TEST_PATTERN:
|
||||
ret = mt9t001_set_output_control(mt9t001,
|
||||
return mt9t001_set_output_control(mt9t001,
|
||||
ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
|
||||
ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
case V4L2_CID_TEST_PATTERN_COLOR:
|
||||
return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
|
||||
|
||||
case V4L2_CID_BLACK_LEVEL_AUTO:
|
||||
|
|
@ -533,12 +532,17 @@ static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
|
|||
.s_ctrl = mt9t001_s_ctrl,
|
||||
};
|
||||
|
||||
static const char * const mt9t001_test_pattern_menu[] = {
|
||||
"Disabled",
|
||||
"Enabled",
|
||||
};
|
||||
|
||||
static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
|
||||
{
|
||||
.ops = &mt9t001_ctrl_ops,
|
||||
.id = V4L2_CID_TEST_PATTERN,
|
||||
.id = V4L2_CID_TEST_PATTERN_COLOR,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Test pattern",
|
||||
.name = "Test Pattern Color",
|
||||
.min = 0,
|
||||
.max = 1023,
|
||||
.step = 1,
|
||||
|
|
@ -741,7 +745,7 @@ static int mt9t001_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
|
||||
v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
|
||||
ARRAY_SIZE(mt9t001_gains) + 3);
|
||||
ARRAY_SIZE(mt9t001_gains) + 4);
|
||||
|
||||
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
|
||||
|
|
@ -752,6 +756,10 @@ static int mt9t001_probe(struct i2c_client *client,
|
|||
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
|
||||
1, pdata->ext_clk);
|
||||
v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||
V4L2_CID_TEST_PATTERN,
|
||||
ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
|
||||
0, mt9t001_test_pattern_menu);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
|
||||
v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
|
||||
|
|
|
|||
|
|
@ -141,6 +141,10 @@ struct mt9v032 {
|
|||
u16 chip_control;
|
||||
u16 aec_agc;
|
||||
u16 hblank;
|
||||
struct {
|
||||
struct v4l2_ctrl *test_pattern;
|
||||
struct v4l2_ctrl *test_pattern_color;
|
||||
};
|
||||
};
|
||||
|
||||
static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
|
||||
|
|
@ -500,7 +504,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
|||
* V4L2 subdev control operations
|
||||
*/
|
||||
|
||||
#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
|
||||
#define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001)
|
||||
|
||||
static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
|
|
@ -545,7 +549,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
break;
|
||||
|
||||
case V4L2_CID_TEST_PATTERN:
|
||||
switch (ctrl->val) {
|
||||
switch (mt9v032->test_pattern->val) {
|
||||
case 0:
|
||||
data = 0;
|
||||
break;
|
||||
|
|
@ -562,13 +566,13 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
| MT9V032_TEST_PATTERN_ENABLE;
|
||||
break;
|
||||
default:
|
||||
data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
|
||||
data = (mt9v032->test_pattern_color->val <<
|
||||
MT9V032_TEST_PATTERN_DATA_SHIFT)
|
||||
| MT9V032_TEST_PATTERN_USE_DATA
|
||||
| MT9V032_TEST_PATTERN_ENABLE
|
||||
| MT9V032_TEST_PATTERN_FLIP;
|
||||
break;
|
||||
}
|
||||
|
||||
return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
|
||||
}
|
||||
|
||||
|
|
@ -579,18 +583,24 @@ static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
|
|||
.s_ctrl = mt9v032_s_ctrl,
|
||||
};
|
||||
|
||||
static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
|
||||
{
|
||||
.ops = &mt9v032_ctrl_ops,
|
||||
.id = V4L2_CID_TEST_PATTERN,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Test pattern",
|
||||
.min = 0,
|
||||
.max = 1023,
|
||||
.step = 1,
|
||||
.def = 0,
|
||||
.flags = 0,
|
||||
}
|
||||
static const char * const mt9v032_test_pattern_menu[] = {
|
||||
"Disabled",
|
||||
"Gray Vertical Shade",
|
||||
"Gray Horizontal Shade",
|
||||
"Gray Diagonal Shade",
|
||||
"Plain",
|
||||
};
|
||||
|
||||
static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
|
||||
.ops = &mt9v032_ctrl_ops,
|
||||
.id = V4L2_CID_TEST_PATTERN_COLOR,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Test Pattern Color",
|
||||
.min = 0,
|
||||
.max = 1023,
|
||||
.step = 1,
|
||||
.def = 0,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
|
@ -741,7 +751,7 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
mutex_init(&mt9v032->power_lock);
|
||||
mt9v032->pdata = pdata;
|
||||
|
||||
v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 8);
|
||||
v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
|
||||
|
||||
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
|
||||
|
|
@ -763,6 +773,14 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN,
|
||||
MT9V032_VERTICAL_BLANKING_MAX, 1,
|
||||
MT9V032_VERTICAL_BLANKING_DEF);
|
||||
mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
|
||||
&mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
|
||||
ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0,
|
||||
mt9v032_test_pattern_menu);
|
||||
mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
|
||||
&mt9v032_test_pattern_color, NULL);
|
||||
|
||||
v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
|
||||
|
||||
mt9v032->pixel_rate =
|
||||
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
|
|
@ -784,8 +802,6 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
v4l2_ctrl_cluster(2, &mt9v032->link_freq);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
|
||||
v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
|
||||
|
||||
mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
|
||||
|
||||
|
|
|
|||
|
|
@ -684,6 +684,11 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
&container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_VFLIP:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@
|
|||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-chip-ident.h>
|
||||
|
||||
#define THS7303_CHANNEL_1 1
|
||||
#define THS7303_CHANNEL_2 2
|
||||
#define THS7303_CHANNEL_3 3
|
||||
|
||||
enum ths7303_filter_mode {
|
||||
THS7303_FILTER_MODE_480I_576I,
|
||||
THS7303_FILTER_MODE_480P_576P,
|
||||
THS7303_FILTER_MODE_720P_1080I,
|
||||
THS7303_FILTER_MODE_1080P,
|
||||
THS7303_FILTER_MODE_DISABLE
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
|
||||
MODULE_AUTHOR("Chaithrika U S");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -37,35 +49,96 @@ module_param(debug, int, 0644);
|
|||
MODULE_PARM_DESC(debug, "Debug level 0-1");
|
||||
|
||||
/* following function is used to set ths7303 */
|
||||
static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std)
|
||||
int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
|
||||
{
|
||||
u8 input_bias_chroma = 3;
|
||||
u8 input_bias_luma = 3;
|
||||
int disable = 0;
|
||||
int err = 0;
|
||||
u8 val;
|
||||
struct i2c_client *client;
|
||||
u8 val = 0;
|
||||
u8 temp;
|
||||
|
||||
client = v4l2_get_subdevdata(sd);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
|
||||
val = 0x02;
|
||||
v4l2_dbg(1, debug, sd, "setting value for SDTV format\n");
|
||||
} else {
|
||||
val = 0x00;
|
||||
v4l2_dbg(1, debug, sd, "disabling all channels\n");
|
||||
if (!client)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mode) {
|
||||
case THS7303_FILTER_MODE_1080P:
|
||||
val = (3 << 6);
|
||||
val |= (3 << 3);
|
||||
break;
|
||||
case THS7303_FILTER_MODE_720P_1080I:
|
||||
val = (2 << 6);
|
||||
val |= (2 << 3);
|
||||
break;
|
||||
case THS7303_FILTER_MODE_480P_576P:
|
||||
val = (1 << 6);
|
||||
val |= (1 << 3);
|
||||
break;
|
||||
case THS7303_FILTER_MODE_480I_576I:
|
||||
break;
|
||||
case THS7303_FILTER_MODE_DISABLE:
|
||||
pr_info("mode disabled\n");
|
||||
/* disable all channels */
|
||||
disable = 1;
|
||||
default:
|
||||
/* disable all channels */
|
||||
disable = 1;
|
||||
}
|
||||
|
||||
err |= i2c_smbus_write_byte_data(client, 0x01, val);
|
||||
err |= i2c_smbus_write_byte_data(client, 0x02, val);
|
||||
err |= i2c_smbus_write_byte_data(client, 0x03, val);
|
||||
|
||||
/* Setup channel 2 - Luma - Green */
|
||||
temp = val;
|
||||
if (!disable)
|
||||
val |= input_bias_luma;
|
||||
err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_2, val);
|
||||
if (err)
|
||||
v4l2_err(sd, "write failed\n");
|
||||
goto out;
|
||||
|
||||
/* setup two chroma channels */
|
||||
if (!disable)
|
||||
temp |= input_bias_chroma;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_1, temp);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_3, temp);
|
||||
if (err)
|
||||
goto out;
|
||||
return err;
|
||||
out:
|
||||
pr_info("write byte data failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
|
||||
{
|
||||
return ths7303_setvalue(sd, norm);
|
||||
if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM))
|
||||
return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
|
||||
else
|
||||
return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
|
||||
}
|
||||
|
||||
/* for setting filter for HD output */
|
||||
static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *dv_timings)
|
||||
{
|
||||
u32 height = dv_timings->bt.height;
|
||||
int interlaced = dv_timings->bt.interlaced;
|
||||
int res = 0;
|
||||
|
||||
if (height == 1080 && !interlaced)
|
||||
res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
|
||||
else if ((height == 720 && !interlaced) ||
|
||||
(height == 1080 && interlaced))
|
||||
res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
|
||||
else if ((height == 480 || height == 576) && !interlaced)
|
||||
res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
|
||||
else
|
||||
/* disable all channels */
|
||||
res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
|
||||
|
|
@ -78,6 +151,7 @@ static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
|
|||
|
||||
static const struct v4l2_subdev_video_ops ths7303_video_ops = {
|
||||
.s_std_output = ths7303_s_std_output,
|
||||
.s_dv_timings = ths7303_s_dv_timings,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_core_ops ths7303_core_ops = {
|
||||
|
|
@ -107,7 +181,7 @@ static int ths7303_probe(struct i2c_client *client,
|
|||
|
||||
v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
|
||||
|
||||
return ths7303_setvalue(sd, std_id);
|
||||
return ths7303_s_std_output(sd, std_id);
|
||||
}
|
||||
|
||||
static int ths7303_remove(struct i2c_client *client)
|
||||
|
|
|
|||
|
|
@ -519,6 +519,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
|
|||
|
||||
*std_id = V4L2_STD_UNKNOWN;
|
||||
|
||||
/* To query the standard the TVP514x must power on the ADCs. */
|
||||
if (!decoder->streaming) {
|
||||
tvp514x_s_stream(sd, 1);
|
||||
msleep(LOCK_RETRY_DELAY);
|
||||
}
|
||||
|
||||
/* query the current standard */
|
||||
current_std = tvp514x_query_current_std(sd);
|
||||
if (current_std == STD_INVALID)
|
||||
|
|
@ -625,25 +631,12 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
|
|||
int err;
|
||||
enum tvp514x_input input_sel;
|
||||
enum tvp514x_output output_sel;
|
||||
u8 sync_lock_status, lock_mask;
|
||||
int try_count = LOCK_RETRY_COUNT;
|
||||
|
||||
if ((input >= INPUT_INVALID) ||
|
||||
(output >= OUTPUT_INVALID))
|
||||
/* Index out of bound */
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* For the sequence streamon -> streamoff and again s_input
|
||||
* it fails to lock the signal, since streamoff puts TVP514x
|
||||
* into power off state which leads to failure in sub-sequent s_input.
|
||||
*
|
||||
* So power up the TVP514x device here, since it is important to lock
|
||||
* the signal at this stage.
|
||||
*/
|
||||
if (!decoder->streaming)
|
||||
tvp514x_s_stream(sd, 1);
|
||||
|
||||
input_sel = input;
|
||||
output_sel = output;
|
||||
|
||||
|
|
@ -660,64 +653,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
|
|||
|
||||
decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
|
||||
decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
|
||||
|
||||
/* Clear status */
|
||||
msleep(LOCK_RETRY_DELAY);
|
||||
err =
|
||||
tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (input_sel) {
|
||||
case INPUT_CVBS_VI1A:
|
||||
case INPUT_CVBS_VI1B:
|
||||
case INPUT_CVBS_VI1C:
|
||||
case INPUT_CVBS_VI2A:
|
||||
case INPUT_CVBS_VI2B:
|
||||
case INPUT_CVBS_VI2C:
|
||||
case INPUT_CVBS_VI3A:
|
||||
case INPUT_CVBS_VI3B:
|
||||
case INPUT_CVBS_VI3C:
|
||||
case INPUT_CVBS_VI4A:
|
||||
lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT |
|
||||
STATUS_HORZ_SYNC_LOCK_BIT |
|
||||
STATUS_VIRT_SYNC_LOCK_BIT;
|
||||
break;
|
||||
|
||||
case INPUT_SVIDEO_VI2A_VI1A:
|
||||
case INPUT_SVIDEO_VI2B_VI1B:
|
||||
case INPUT_SVIDEO_VI2C_VI1C:
|
||||
case INPUT_SVIDEO_VI2A_VI3A:
|
||||
case INPUT_SVIDEO_VI2B_VI3B:
|
||||
case INPUT_SVIDEO_VI2C_VI3C:
|
||||
case INPUT_SVIDEO_VI4A_VI1A:
|
||||
case INPUT_SVIDEO_VI4A_VI1B:
|
||||
case INPUT_SVIDEO_VI4A_VI1C:
|
||||
case INPUT_SVIDEO_VI4A_VI3A:
|
||||
case INPUT_SVIDEO_VI4A_VI3B:
|
||||
case INPUT_SVIDEO_VI4A_VI3C:
|
||||
lock_mask = STATUS_HORZ_SYNC_LOCK_BIT |
|
||||
STATUS_VIRT_SYNC_LOCK_BIT;
|
||||
break;
|
||||
/* Need to add other interfaces*/
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (try_count-- > 0) {
|
||||
/* Allow decoder to sync up with new input */
|
||||
msleep(LOCK_RETRY_DELAY);
|
||||
|
||||
sync_lock_status = tvp514x_read_reg(sd,
|
||||
REG_STATUS1);
|
||||
if (lock_mask == (sync_lock_status & lock_mask))
|
||||
/* Input detected */
|
||||
break;
|
||||
}
|
||||
|
||||
if (try_count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
decoder->input = input;
|
||||
decoder->output = output;
|
||||
|
||||
|
|
|
|||
|
|
@ -668,6 +668,12 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
|
|||
.default_value = 32768,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
},{
|
||||
.id = V4L2_CID_COLOR_KILLER,
|
||||
.name = "Color killer",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
}, {
|
||||
.id = V4L2_CID_HUE,
|
||||
.name = "Hue",
|
||||
.minimum = 0,
|
||||
|
|
@ -1474,6 +1480,9 @@ static int bttv_g_ctrl(struct file *file, void *priv,
|
|||
case V4L2_CID_SATURATION:
|
||||
c->value = btv->saturation;
|
||||
break;
|
||||
case V4L2_CID_COLOR_KILLER:
|
||||
c->value = btv->opt_color_killer;
|
||||
break;
|
||||
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
|
|
@ -1526,7 +1535,6 @@ static int bttv_s_ctrl(struct file *file, void *f,
|
|||
struct v4l2_control *c)
|
||||
{
|
||||
int err;
|
||||
int val;
|
||||
struct bttv_fh *fh = f;
|
||||
struct bttv *btv = fh->btv;
|
||||
|
||||
|
|
@ -1547,6 +1555,16 @@ static int bttv_s_ctrl(struct file *file, void *f,
|
|||
case V4L2_CID_SATURATION:
|
||||
bt848_sat(btv, c->value);
|
||||
break;
|
||||
case V4L2_CID_COLOR_KILLER:
|
||||
btv->opt_color_killer = c->value;
|
||||
if (btv->opt_color_killer) {
|
||||
btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
|
||||
btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
|
||||
} else {
|
||||
btand(~BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
|
||||
btand(~BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
|
||||
}
|
||||
break;
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
audio_mute(btv, c->value);
|
||||
/* fall through */
|
||||
|
|
@ -1564,9 +1582,13 @@ static int bttv_s_ctrl(struct file *file, void *f,
|
|||
|
||||
case V4L2_CID_PRIVATE_CHROMA_AGC:
|
||||
btv->opt_chroma_agc = c->value;
|
||||
val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
|
||||
btwrite(val, BT848_E_SCLOOP);
|
||||
btwrite(val, BT848_O_SCLOOP);
|
||||
if (btv->opt_chroma_agc) {
|
||||
btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
|
||||
btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
|
||||
} else {
|
||||
btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
|
||||
btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
|
||||
}
|
||||
break;
|
||||
case V4L2_CID_PRIVATE_COMBFILTER:
|
||||
btv->opt_combfilter = c->value;
|
||||
|
|
|
|||
|
|
@ -429,6 +429,7 @@ struct bttv {
|
|||
int opt_lumafilter;
|
||||
int opt_automute;
|
||||
int opt_chroma_agc;
|
||||
int opt_color_killer;
|
||||
int opt_adc_crush;
|
||||
int opt_vcr_hack;
|
||||
int opt_whitecrush_upper;
|
||||
|
|
|
|||
|
|
@ -646,7 +646,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
|
|||
dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
|
||||
default:
|
||||
result = -EOPNOTSUPP;
|
||||
};
|
||||
}
|
||||
free_mem_and_exit:
|
||||
kfree (p_ca_message);
|
||||
kfree (p_ca_slot_info);
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ static void netup_read_ci_status(struct work_struct *work)
|
|||
DVB_CA_EN50221_POLL_CAM_READY : 0);
|
||||
ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
|
||||
__func__, inter->state[1]->status);
|
||||
};
|
||||
}
|
||||
|
||||
if (inter->state[0] != NULL) {
|
||||
inter->state[0]->status =
|
||||
|
|
@ -425,7 +425,7 @@ static void netup_read_ci_status(struct work_struct *work)
|
|||
DVB_CA_EN50221_POLL_CAM_READY : 0);
|
||||
ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
|
||||
__func__, inter->state[0]->status);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* CI irq handler */
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
|
|||
0, &store, 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
state->current_ci_flag = flag;
|
||||
|
||||
mutex_lock(&dev->gpio_lock);
|
||||
|
|
|
|||
|
|
@ -542,11 +542,13 @@ struct cx23885_board cx23885_boards[] = {
|
|||
{
|
||||
.type = CX23885_VMUX_COMPOSITE1,
|
||||
.vmux = CX25840_COMPOSITE8,
|
||||
.amux = CX25840_AUDIO7,
|
||||
},
|
||||
{
|
||||
.type = CX23885_VMUX_SVIDEO,
|
||||
.vmux = CX25840_SVIDEO_LUMA3 |
|
||||
CX25840_SVIDEO_CHROMA4,
|
||||
.amux = CX25840_AUDIO7,
|
||||
},
|
||||
{
|
||||
.type = CX23885_VMUX_COMPONENT,
|
||||
|
|
@ -554,6 +556,7 @@ struct cx23885_board cx23885_boards[] = {
|
|||
CX25840_VIN1_CH1 |
|
||||
CX25840_VIN6_CH2 |
|
||||
CX25840_VIN7_CH3,
|
||||
.amux = CX25840_AUDIO7,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -508,7 +508,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
|
|||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
|
||||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
|
||||
(dev->board == CX23885_BOARD_MYGICA_X8507)) {
|
||||
/* Configure audio routing */
|
||||
v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
|
||||
INPUT(input)->amux, 0, 0);
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
|
|||
}
|
||||
|
||||
/* Default if filename is empty string */
|
||||
if (strcmp(dev->input_filename_ch2, "") == 0) {
|
||||
if (strcmp(dev->_filename_ch2, "") == 0) {
|
||||
if (dev->_isNTSC_ch2) {
|
||||
dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
|
||||
PIXEL_FRMT_411) ? "/root/vid411.yuv" :
|
||||
|
|
|
|||
|
|
@ -808,7 +808,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
|
|||
}
|
||||
|
||||
/* Default if filename is empty string */
|
||||
if (strcmp(dev->input_filename, "") == 0) {
|
||||
if (strcmp(dev->_filename, "") == 0) {
|
||||
if (dev->_isNTSC) {
|
||||
dev->_filename =
|
||||
(dev->_pixel_format == PIXEL_FRMT_411) ?
|
||||
|
|
|
|||
|
|
@ -721,7 +721,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
|
|||
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.width = dev->width;
|
||||
f->fmt.pix.height = dev->height;
|
||||
|
|
@ -739,7 +739,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
|
|||
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
|
||||
dev->width, dev->height, fh->mpegq.field );
|
||||
|
|
@ -755,7 +755,7 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
|
|||
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
dev->width = f->fmt.pix.width;
|
||||
dev->height = f->fmt.pix.height;
|
||||
|
|
|
|||
|
|
@ -896,7 +896,7 @@ static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
|
|||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
|
|||
cx88_core_irq(core,status);
|
||||
if (status & PCI_INT_TSINT)
|
||||
cx8802_mpeg_irq(dev);
|
||||
};
|
||||
}
|
||||
if (MAX_IRQ_LOOP == loop) {
|
||||
dprintk( 0, "clearing mask\n" );
|
||||
printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
|
|||
set_audio_registers(core, nicam_bgdki_common);
|
||||
set_audio_registers(core, nicam_default);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
|
||||
set_audio_finish(core, mode);
|
||||
|
|
@ -639,7 +639,7 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
|
|||
dprintk("%s Warning: wrong value\n", __func__);
|
||||
return;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
|
||||
set_audio_finish(core, mode);
|
||||
|
|
|
|||
|
|
@ -1535,7 +1535,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
|
|||
cx88_core_irq(core,status);
|
||||
if (status & PCI_INT_VIDINT)
|
||||
cx8800_vid_irq(dev);
|
||||
};
|
||||
}
|
||||
if (10 == loop) {
|
||||
printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
|
||||
core->name);
|
||||
|
|
|
|||
|
|
@ -1204,7 +1204,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str
|
|||
break;
|
||||
default:
|
||||
/* nothing */;
|
||||
};
|
||||
}
|
||||
switch (c->id) {
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
dev->ctl_bright = c->value;
|
||||
|
|
|
|||
|
|
@ -165,12 +165,12 @@ config VIDEO_SAMSUNG_S5P_JPEG
|
|||
This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
|
||||
|
||||
config VIDEO_SAMSUNG_S5P_MFC
|
||||
tristate "Samsung S5P MFC 5.1 Video Codec"
|
||||
tristate "Samsung S5P MFC Video Codec"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
default n
|
||||
help
|
||||
MFC 5.1 driver for V4L2.
|
||||
MFC 5.1 and 6.x driver for V4L2
|
||||
|
||||
config VIDEO_MX2_EMMAPRP
|
||||
tristate "MX2 eMMa-PrP support"
|
||||
|
|
|
|||
|
|
@ -174,26 +174,6 @@ static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev,
|
||||
unsigned int dv_preset)
|
||||
{
|
||||
struct vpbe_config *cfg = vpbe_dev->cfg;
|
||||
struct vpbe_enc_mode_info var;
|
||||
int curr_output = vpbe_dev->current_out_index;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
|
||||
var = cfg->outputs[curr_output].modes[i];
|
||||
if ((var.timings_type & VPBE_ENC_DV_PRESET) &&
|
||||
(var.timings.dv_preset == dv_preset)) {
|
||||
vpbe_dev->current_timings = var;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get std by std id */
|
||||
static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
|
||||
v4l2_std_id std_id)
|
||||
|
|
@ -206,7 +186,7 @@ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
|
|||
for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
|
||||
var = cfg->outputs[curr_output].modes[i];
|
||||
if ((var.timings_type & VPBE_ENC_STD) &&
|
||||
(var.timings.std_id & std_id)) {
|
||||
(var.std_id & std_id)) {
|
||||
vpbe_dev->current_timings = var;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -344,38 +324,42 @@ static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
|
|||
}
|
||||
|
||||
/**
|
||||
* vpbe_s_dv_preset - Set the given preset timings in the encoder
|
||||
* vpbe_s_dv_timings - Set the given preset timings in the encoder
|
||||
*
|
||||
* Sets the preset if supported by the current encoder. Return the status.
|
||||
* Sets the timings if supported by the current encoder. Return the status.
|
||||
* 0 - success & -EINVAL on error
|
||||
*/
|
||||
static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_dv_preset *dv_preset)
|
||||
static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_dv_timings *dv_timings)
|
||||
{
|
||||
struct vpbe_config *cfg = vpbe_dev->cfg;
|
||||
int out_index = vpbe_dev->current_out_index;
|
||||
struct vpbe_output *output = &cfg->outputs[out_index];
|
||||
int sd_index = vpbe_dev->current_sd_index;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
|
||||
if (!(cfg->outputs[out_index].output.capabilities &
|
||||
V4L2_OUT_CAP_PRESETS))
|
||||
V4L2_OUT_CAP_DV_TIMINGS))
|
||||
return -EINVAL;
|
||||
|
||||
ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < output->num_modes; i++) {
|
||||
if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS &&
|
||||
!memcmp(&output->modes[i].dv_timings,
|
||||
dv_timings, sizeof(*dv_timings)))
|
||||
break;
|
||||
}
|
||||
if (i >= output->num_modes)
|
||||
return -EINVAL;
|
||||
vpbe_dev->current_timings = output->modes[i];
|
||||
mutex_lock(&vpbe_dev->lock);
|
||||
|
||||
|
||||
ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
|
||||
s_dv_preset, dv_preset);
|
||||
s_dv_timings, dv_timings);
|
||||
if (!ret && (vpbe_dev->amp != NULL)) {
|
||||
/* Call amplifier subdevice */
|
||||
ret = v4l2_subdev_call(vpbe_dev->amp, video,
|
||||
s_dv_preset, dv_preset);
|
||||
s_dv_timings, dv_timings);
|
||||
}
|
||||
/* set the lcd controller output for the given mode */
|
||||
if (!ret) {
|
||||
|
|
@ -392,17 +376,17 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* vpbe_g_dv_preset - Get the preset in the current encoder
|
||||
* vpbe_g_dv_timings - Get the timings in the current encoder
|
||||
*
|
||||
* Get the preset in the current encoder. Return the status. 0 - success
|
||||
* Get the timings in the current encoder. Return the status. 0 - success
|
||||
* -EINVAL on error
|
||||
*/
|
||||
static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_dv_preset *dv_preset)
|
||||
static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_dv_timings *dv_timings)
|
||||
{
|
||||
if (vpbe_dev->current_timings.timings_type &
|
||||
VPBE_ENC_DV_PRESET) {
|
||||
dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset;
|
||||
VPBE_ENC_CUSTOM_TIMINGS) {
|
||||
*dv_timings = vpbe_dev->current_timings.dv_timings;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -410,13 +394,13 @@ static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder
|
||||
* vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder
|
||||
*
|
||||
* Get the preset in the current encoder. Return the status. 0 - success
|
||||
* Get the timings in the current encoder. Return the status. 0 - success
|
||||
* -EINVAL on error
|
||||
*/
|
||||
static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_dv_enum_preset *preset_info)
|
||||
static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
|
||||
struct v4l2_enum_dv_timings *timings)
|
||||
{
|
||||
struct vpbe_config *cfg = vpbe_dev->cfg;
|
||||
int out_index = vpbe_dev->current_out_index;
|
||||
|
|
@ -424,12 +408,12 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
|
|||
int j = 0;
|
||||
int i;
|
||||
|
||||
if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS))
|
||||
if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < output->num_modes; i++) {
|
||||
if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) {
|
||||
if (j == preset_info->index)
|
||||
if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) {
|
||||
if (j == timings->index)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
|
|
@ -437,9 +421,8 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
|
|||
|
||||
if (i == output->num_modes)
|
||||
return -EINVAL;
|
||||
|
||||
return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset,
|
||||
preset_info);
|
||||
timings->timings = output->modes[i].dv_timings;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -489,10 +472,10 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
|
|||
*/
|
||||
static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
|
||||
{
|
||||
struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings;
|
||||
struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
|
||||
|
||||
if (cur_timings.timings_type & VPBE_ENC_STD) {
|
||||
*std_id = cur_timings.timings.std_id;
|
||||
if (cur_timings->timings_type & VPBE_ENC_STD) {
|
||||
*std_id = cur_timings->std_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +494,7 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
|
|||
{
|
||||
struct vpbe_enc_mode_info *preset_mode = NULL;
|
||||
struct vpbe_config *cfg = vpbe_dev->cfg;
|
||||
struct v4l2_dv_preset dv_preset;
|
||||
struct v4l2_dv_timings dv_timings;
|
||||
struct osd_state *osd_device;
|
||||
int out_index = vpbe_dev->current_out_index;
|
||||
int ret = 0;
|
||||
|
|
@ -530,11 +513,12 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
|
|||
*/
|
||||
if (preset_mode->timings_type & VPBE_ENC_STD)
|
||||
return vpbe_s_std(vpbe_dev,
|
||||
&preset_mode->timings.std_id);
|
||||
if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) {
|
||||
dv_preset.preset =
|
||||
preset_mode->timings.dv_preset;
|
||||
return vpbe_s_dv_preset(vpbe_dev, &dv_preset);
|
||||
&preset_mode->std_id);
|
||||
if (preset_mode->timings_type &
|
||||
VPBE_ENC_CUSTOM_TIMINGS) {
|
||||
dv_timings =
|
||||
preset_mode->dv_timings;
|
||||
return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -626,11 +610,11 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
|
||||
if (IS_ERR(vpbe_dev->dac_clk)) {
|
||||
ret = PTR_ERR(vpbe_dev->dac_clk);
|
||||
goto vpbe_unlock;
|
||||
goto fail_mutex_unlock;
|
||||
}
|
||||
if (clk_enable(vpbe_dev->dac_clk)) {
|
||||
ret = -ENODEV;
|
||||
goto vpbe_unlock;
|
||||
goto fail_mutex_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -642,7 +626,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
if (ret) {
|
||||
v4l2_err(dev->driver,
|
||||
"Unable to register v4l2 device.\n");
|
||||
goto vpbe_fail_clock;
|
||||
goto fail_clk_put;
|
||||
}
|
||||
v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
|
||||
|
||||
|
|
@ -658,7 +642,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
v4l2_err(&vpbe_dev->v4l2_dev,
|
||||
"vpbe unable to init venc sub device\n");
|
||||
ret = -ENODEV;
|
||||
goto vpbe_fail_v4l2_device;
|
||||
goto fail_dev_unregister;
|
||||
}
|
||||
/* initialize osd device */
|
||||
osd_device = vpbe_dev->osd_device;
|
||||
|
|
@ -669,7 +653,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
v4l2_err(&vpbe_dev->v4l2_dev,
|
||||
"unable to initialize the OSD device");
|
||||
err = -ENOMEM;
|
||||
goto vpbe_fail_v4l2_device;
|
||||
goto fail_dev_unregister;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -685,7 +669,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
v4l2_err(&vpbe_dev->v4l2_dev,
|
||||
"unable to allocate memory for encoders sub devices");
|
||||
ret = -ENOMEM;
|
||||
goto vpbe_fail_v4l2_device;
|
||||
goto fail_dev_unregister;
|
||||
}
|
||||
|
||||
i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
|
||||
|
|
@ -711,7 +695,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
" failed to register",
|
||||
enc_info->module_name);
|
||||
ret = -ENODEV;
|
||||
goto vpbe_fail_sd_register;
|
||||
goto fail_kfree_encoders;
|
||||
}
|
||||
} else
|
||||
v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
|
||||
|
|
@ -730,7 +714,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
"amplifier %s failed to register",
|
||||
amp_info->module_name);
|
||||
ret = -ENODEV;
|
||||
goto vpbe_fail_amp_register;
|
||||
goto fail_kfree_encoders;
|
||||
}
|
||||
v4l2_info(&vpbe_dev->v4l2_dev,
|
||||
"v4l2 sub device %s registered\n",
|
||||
|
|
@ -770,16 +754,14 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
|
|||
/* TBD handling of bootargs for default output and mode */
|
||||
return 0;
|
||||
|
||||
vpbe_fail_amp_register:
|
||||
kfree(vpbe_dev->amp);
|
||||
vpbe_fail_sd_register:
|
||||
fail_kfree_encoders:
|
||||
kfree(vpbe_dev->encoders);
|
||||
vpbe_fail_v4l2_device:
|
||||
fail_dev_unregister:
|
||||
v4l2_device_unregister(&vpbe_dev->v4l2_dev);
|
||||
vpbe_fail_clock:
|
||||
fail_clk_put:
|
||||
if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
|
||||
clk_put(vpbe_dev->dac_clk);
|
||||
vpbe_unlock:
|
||||
fail_mutex_unlock:
|
||||
mutex_unlock(&vpbe_dev->lock);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -810,9 +792,9 @@ static struct vpbe_device_ops vpbe_dev_ops = {
|
|||
.enum_outputs = vpbe_enum_outputs,
|
||||
.set_output = vpbe_set_output,
|
||||
.get_output = vpbe_get_output,
|
||||
.s_dv_preset = vpbe_s_dv_preset,
|
||||
.g_dv_preset = vpbe_g_dv_preset,
|
||||
.enum_dv_presets = vpbe_enum_dv_presets,
|
||||
.s_dv_timings = vpbe_s_dv_timings,
|
||||
.g_dv_timings = vpbe_g_dv_timings,
|
||||
.enum_dv_timings = vpbe_enum_dv_timings,
|
||||
.s_std = vpbe_s_std,
|
||||
.g_std = vpbe_g_std,
|
||||
.initialize = vpbe_initialize,
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
|
|||
int h_scale;
|
||||
int v_scale;
|
||||
|
||||
v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id;
|
||||
v4l2_std_id standard_id = vpbe_dev->current_timings.std_id;
|
||||
|
||||
/*
|
||||
* Application initially set the image format. Current display
|
||||
|
|
@ -637,7 +637,7 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
|
|||
struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
|
||||
struct osd_layer_config *cfg = &layer->layer_info.config;
|
||||
struct osd_state *osd_device = disp_dev->osd_device;
|
||||
struct v4l2_rect *rect = &crop->c;
|
||||
struct v4l2_rect rect = crop->c;
|
||||
int ret;
|
||||
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
|
||||
|
|
@ -648,21 +648,21 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rect->top < 0)
|
||||
rect->top = 0;
|
||||
if (rect->left < 0)
|
||||
rect->left = 0;
|
||||
if (rect.top < 0)
|
||||
rect.top = 0;
|
||||
if (rect.left < 0)
|
||||
rect.left = 0;
|
||||
|
||||
vpbe_disp_check_window_params(disp_dev, rect);
|
||||
vpbe_disp_check_window_params(disp_dev, &rect);
|
||||
|
||||
osd_device->ops.get_layer_config(osd_device,
|
||||
layer->layer_info.id, cfg);
|
||||
|
||||
vpbe_disp_calculate_scale_factor(disp_dev, layer,
|
||||
rect->width,
|
||||
rect->height);
|
||||
vpbe_disp_adj_position(disp_dev, layer, rect->top,
|
||||
rect->left);
|
||||
rect.width,
|
||||
rect.height);
|
||||
vpbe_disp_adj_position(disp_dev, layer, rect.top,
|
||||
rect.left);
|
||||
ret = osd_device->ops.set_layer_config(osd_device,
|
||||
layer->layer_info.id, cfg);
|
||||
if (ret < 0) {
|
||||
|
|
@ -943,7 +943,7 @@ static int vpbe_display_g_std(struct file *file, void *priv,
|
|||
|
||||
/* Get the standard from the current encoder */
|
||||
if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) {
|
||||
*std_id = vpbe_dev->current_timings.timings.std_id;
|
||||
*std_id = vpbe_dev->current_timings.std_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1029,29 +1029,29 @@ static int vpbe_display_g_output(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/**
|
||||
* vpbe_display_enum_dv_presets - Enumerate the dv presets
|
||||
* vpbe_display_enum_dv_timings - Enumerate the dv timings
|
||||
*
|
||||
* enum the preset in the current encoder. Return the status. 0 - success
|
||||
* enum the timings in the current encoder. Return the status. 0 - success
|
||||
* -EINVAL on error
|
||||
*/
|
||||
static int
|
||||
vpbe_display_enum_dv_presets(struct file *file, void *priv,
|
||||
struct v4l2_dv_enum_preset *preset)
|
||||
vpbe_display_enum_dv_timings(struct file *file, void *priv,
|
||||
struct v4l2_enum_dv_timings *timings)
|
||||
{
|
||||
struct vpbe_fh *fh = priv;
|
||||
struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
|
||||
int ret;
|
||||
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n");
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n");
|
||||
|
||||
/* Enumerate outputs */
|
||||
if (NULL == vpbe_dev->ops.enum_dv_presets)
|
||||
if (NULL == vpbe_dev->ops.enum_dv_timings)
|
||||
return -EINVAL;
|
||||
|
||||
ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset);
|
||||
ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings);
|
||||
if (ret) {
|
||||
v4l2_err(&vpbe_dev->v4l2_dev,
|
||||
"Failed to enumerate dv presets info\n");
|
||||
"Failed to enumerate dv timings info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1059,21 +1059,21 @@ vpbe_display_enum_dv_presets(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/**
|
||||
* vpbe_display_s_dv_preset - Set the dv presets
|
||||
* vpbe_display_s_dv_timings - Set the dv timings
|
||||
*
|
||||
* Set the preset in the current encoder. Return the status. 0 - success
|
||||
* Set the timings in the current encoder. Return the status. 0 - success
|
||||
* -EINVAL on error
|
||||
*/
|
||||
static int
|
||||
vpbe_display_s_dv_preset(struct file *file, void *priv,
|
||||
struct v4l2_dv_preset *preset)
|
||||
vpbe_display_s_dv_timings(struct file *file, void *priv,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
struct vpbe_fh *fh = priv;
|
||||
struct vpbe_layer *layer = fh->layer;
|
||||
struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
|
||||
int ret;
|
||||
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n");
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n");
|
||||
|
||||
|
||||
/* If streaming is started, return error */
|
||||
|
|
@ -1083,13 +1083,13 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/* Set the given standard in the encoder */
|
||||
if (!vpbe_dev->ops.s_dv_preset)
|
||||
if (!vpbe_dev->ops.s_dv_timings)
|
||||
return -EINVAL;
|
||||
|
||||
ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset);
|
||||
ret = vpbe_dev->ops.s_dv_timings(vpbe_dev, timings);
|
||||
if (ret) {
|
||||
v4l2_err(&vpbe_dev->v4l2_dev,
|
||||
"Failed to set the dv presets info\n");
|
||||
"Failed to set the dv timings info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* set the current norm to zero to be consistent. If STD is used
|
||||
|
|
@ -1101,26 +1101,25 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/**
|
||||
* vpbe_display_g_dv_preset - Set the dv presets
|
||||
* vpbe_display_g_dv_timings - Set the dv timings
|
||||
*
|
||||
* Get the preset in the current encoder. Return the status. 0 - success
|
||||
* Get the timings in the current encoder. Return the status. 0 - success
|
||||
* -EINVAL on error
|
||||
*/
|
||||
static int
|
||||
vpbe_display_g_dv_preset(struct file *file, void *priv,
|
||||
struct v4l2_dv_preset *dv_preset)
|
||||
vpbe_display_g_dv_timings(struct file *file, void *priv,
|
||||
struct v4l2_dv_timings *dv_timings)
|
||||
{
|
||||
struct vpbe_fh *fh = priv;
|
||||
struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
|
||||
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n");
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n");
|
||||
|
||||
/* Get the given standard in the encoder */
|
||||
|
||||
if (vpbe_dev->current_timings.timings_type &
|
||||
VPBE_ENC_DV_PRESET) {
|
||||
dv_preset->preset =
|
||||
vpbe_dev->current_timings.timings.dv_preset;
|
||||
VPBE_ENC_CUSTOM_TIMINGS) {
|
||||
*dv_timings = vpbe_dev->current_timings.dv_timings;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1572,9 +1571,9 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {
|
|||
.vidioc_enum_output = vpbe_display_enum_output,
|
||||
.vidioc_s_output = vpbe_display_s_output,
|
||||
.vidioc_g_output = vpbe_display_g_output,
|
||||
.vidioc_s_dv_preset = vpbe_display_s_dv_preset,
|
||||
.vidioc_g_dv_preset = vpbe_display_g_dv_preset,
|
||||
.vidioc_enum_dv_presets = vpbe_display_enum_dv_presets,
|
||||
.vidioc_s_dv_timings = vpbe_display_s_dv_timings,
|
||||
.vidioc_g_dv_timings = vpbe_display_g_dv_timings,
|
||||
.vidioc_enum_dv_timings = vpbe_display_enum_dv_timings,
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.vidioc_g_register = vpbe_display_g_register,
|
||||
.vidioc_s_register = vpbe_display_s_register,
|
||||
|
|
@ -1639,8 +1638,7 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
|
|||
VPBE_ENC_STD) {
|
||||
vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
|
||||
vbd->current_norm =
|
||||
disp_dev->vpbe_dev->
|
||||
current_timings.timings.std_id;
|
||||
disp_dev->vpbe_dev->current_timings.std_id;
|
||||
} else
|
||||
vbd->current_norm = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
|
|||
return -EINVAL;
|
||||
|
||||
/* Setup clock at VPSS & VENC for SD */
|
||||
if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
|
||||
if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
venc_enabledigitaloutput(sd, 0);
|
||||
|
|
@ -345,7 +345,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
|
|||
(pdata->venc_type != VPBE_VERSION_2))
|
||||
return -EINVAL;
|
||||
/* Setup clock at VPSS & VENC for SD */
|
||||
if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
|
||||
if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
venc_enabledigitaloutput(sd, 0);
|
||||
|
|
@ -385,7 +385,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd)
|
|||
struct venc_state *venc = to_state(sd);
|
||||
struct venc_platform_data *pdata = venc->pdata;
|
||||
|
||||
if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0)
|
||||
if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
venc_enabledigitaloutput(sd, 0);
|
||||
|
|
@ -413,7 +413,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
|
|||
struct venc_state *venc = to_state(sd);
|
||||
struct venc_platform_data *pdata = venc->pdata;
|
||||
|
||||
if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0)
|
||||
if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
venc_enabledigitaloutput(sd, 0);
|
||||
|
|
@ -446,26 +446,27 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int venc_s_dv_preset(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_preset *dv_preset)
|
||||
static int venc_s_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *dv_timings)
|
||||
{
|
||||
struct venc_state *venc = to_state(sd);
|
||||
u32 height = dv_timings->bt.height;
|
||||
int ret;
|
||||
|
||||
v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
|
||||
v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
|
||||
|
||||
if (dv_preset->preset == V4L2_DV_576P50)
|
||||
if (height == 576)
|
||||
return venc_set_576p50(sd);
|
||||
else if (dv_preset->preset == V4L2_DV_480P59_94)
|
||||
else if (height == 480)
|
||||
return venc_set_480p59_94(sd);
|
||||
else if ((dv_preset->preset == V4L2_DV_720P60) &&
|
||||
else if ((height == 720) &&
|
||||
(venc->pdata->venc_type == VPBE_VERSION_2)) {
|
||||
/* TBD setup internal 720p mode here */
|
||||
ret = venc_set_720p60_internal(sd);
|
||||
/* for DM365 VPBE, there is DAC inside */
|
||||
vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
|
||||
return ret;
|
||||
} else if ((dv_preset->preset == V4L2_DV_1080I30) &&
|
||||
} else if ((height == 1080) &&
|
||||
(venc->pdata->venc_type == VPBE_VERSION_2)) {
|
||||
/* TBD setup internal 1080i mode here */
|
||||
ret = venc_set_1080i30_internal(sd);
|
||||
|
|
@ -518,7 +519,7 @@ static const struct v4l2_subdev_core_ops venc_core_ops = {
|
|||
static const struct v4l2_subdev_video_ops venc_video_ops = {
|
||||
.s_routing = venc_s_routing,
|
||||
.s_std_output = venc_s_std_output,
|
||||
.s_dv_preset = venc_s_dv_preset,
|
||||
.s_dv_timings = venc_s_dv_timings,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops venc_ops = {
|
||||
|
|
|
|||
|
|
@ -1669,6 +1669,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
|
|||
const struct v4l2_crop *crop)
|
||||
{
|
||||
struct vpfe_device *vpfe_dev = video_drvdata(file);
|
||||
struct v4l2_rect rect = crop->c;
|
||||
int ret = 0;
|
||||
|
||||
v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
|
||||
|
|
@ -1684,7 +1685,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (crop->c.top < 0 || crop->c.left < 0) {
|
||||
if (rect.top < 0 || rect.left < 0) {
|
||||
v4l2_err(&vpfe_dev->v4l2_dev,
|
||||
"doesn't support negative values for top & left\n");
|
||||
ret = -EINVAL;
|
||||
|
|
@ -1692,26 +1693,26 @@ static int vpfe_s_crop(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/* adjust the width to 16 pixel boundary */
|
||||
crop->c.width = ((crop->c.width + 15) & ~0xf);
|
||||
rect.width = ((rect.width + 15) & ~0xf);
|
||||
|
||||
/* make sure parameters are valid */
|
||||
if ((crop->c.left + crop->c.width >
|
||||
if ((rect.left + rect.width >
|
||||
vpfe_dev->std_info.active_pixels) ||
|
||||
(crop->c.top + crop->c.height >
|
||||
(rect.top + rect.height >
|
||||
vpfe_dev->std_info.active_lines)) {
|
||||
v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock_out;
|
||||
}
|
||||
ccdc_dev->hw_ops.set_image_window(&crop->c);
|
||||
vpfe_dev->fmt.fmt.pix.width = crop->c.width;
|
||||
vpfe_dev->fmt.fmt.pix.height = crop->c.height;
|
||||
ccdc_dev->hw_ops.set_image_window(&rect);
|
||||
vpfe_dev->fmt.fmt.pix.width = rect.width;
|
||||
vpfe_dev->fmt.fmt.pix.height = rect.height;
|
||||
vpfe_dev->fmt.fmt.pix.bytesperline =
|
||||
ccdc_dev->hw_ops.get_line_length();
|
||||
vpfe_dev->fmt.fmt.pix.sizeimage =
|
||||
vpfe_dev->fmt.fmt.pix.bytesperline *
|
||||
vpfe_dev->fmt.fmt.pix.height;
|
||||
vpfe_dev->crop = crop->c;
|
||||
vpfe_dev->crop = rect;
|
||||
unlock_out:
|
||||
mutex_unlock(&vpfe_dev->lock);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -311,12 +311,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
}
|
||||
|
||||
/* configure 1 or 2 channel mode */
|
||||
ret = vpif_config_data->setup_input_channel_mode
|
||||
(vpif->std_info.ycmux_mode);
|
||||
|
||||
if (ret < 0) {
|
||||
vpif_dbg(1, debug, "can't set vpif channel mode\n");
|
||||
return ret;
|
||||
if (vpif_config_data->setup_input_channel_mode) {
|
||||
ret = vpif_config_data->
|
||||
setup_input_channel_mode(vpif->std_info.ycmux_mode);
|
||||
if (ret < 0) {
|
||||
vpif_dbg(1, debug, "can't set vpif channel mode\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call vpif_set_params function to set the parameters and addresses */
|
||||
|
|
@ -863,13 +864,11 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait)
|
|||
*/
|
||||
static int vpif_open(struct file *filep)
|
||||
{
|
||||
struct vpif_capture_config *config = vpif_dev->platform_data;
|
||||
struct video_device *vdev = video_devdata(filep);
|
||||
struct common_obj *common;
|
||||
struct video_obj *vid_ch;
|
||||
struct channel_obj *ch;
|
||||
struct vpif_fh *fh;
|
||||
int i;
|
||||
|
||||
vpif_dbg(2, debug, "vpif_open\n");
|
||||
|
||||
|
|
@ -878,26 +877,6 @@ static int vpif_open(struct file *filep)
|
|||
vid_ch = &ch->video;
|
||||
common = &ch->common[VPIF_VIDEO_INDEX];
|
||||
|
||||
if (NULL == ch->curr_subdev_info) {
|
||||
/**
|
||||
* search through the sub device to see a registered
|
||||
* sub device and make it as current sub device
|
||||
*/
|
||||
for (i = 0; i < config->subdev_count; i++) {
|
||||
if (vpif_obj.sd[i]) {
|
||||
/* the sub device is registered */
|
||||
ch->curr_subdev_info = &config->subdev_info[i];
|
||||
/* make first input as the current input */
|
||||
vid_ch->input_idx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == config->subdev_count) {
|
||||
vpif_err("No sub device registered\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory for the file handle object */
|
||||
fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
|
||||
if (NULL == fh) {
|
||||
|
|
@ -997,6 +976,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
|
|||
struct common_obj *common;
|
||||
u8 index = 0;
|
||||
struct vb2_queue *q;
|
||||
int ret;
|
||||
|
||||
vpif_dbg(2, debug, "vpif_reqbufs\n");
|
||||
|
||||
|
|
@ -1036,8 +1016,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
|
|||
q->mem_ops = &vb2_dma_contig_memops;
|
||||
q->buf_struct_size = sizeof(struct vpif_cap_buffer);
|
||||
|
||||
vb2_queue_init(q);
|
||||
|
||||
ret = vb2_queue_init(q);
|
||||
if (ret) {
|
||||
vpif_err("vpif_capture: vb2_queue_init() failed\n");
|
||||
vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
|
||||
return ret;
|
||||
}
|
||||
/* Set io allowed member of file handle to TRUE */
|
||||
fh->io_allowed[index] = 1;
|
||||
/* Increment io usrs member of channel object to 1 */
|
||||
|
|
@ -1175,10 +1159,9 @@ static int vpif_streamon(struct file *file, void *priv,
|
|||
return ret;
|
||||
|
||||
/* Enable streamon on the sub device */
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
|
||||
s_stream, 1);
|
||||
ret = v4l2_subdev_call(ch->sd, video, s_stream, 1);
|
||||
|
||||
if (ret && (ret != -ENOIOCTLCMD)) {
|
||||
if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
|
||||
vpif_dbg(1, debug, "stream on failed in subdev\n");
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1238,73 +1221,105 @@ static int vpif_streamoff(struct file *file, void *priv,
|
|||
|
||||
common->started = 0;
|
||||
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
|
||||
s_stream, 0);
|
||||
ret = v4l2_subdev_call(ch->sd, video, s_stream, 0);
|
||||
|
||||
if (ret && (ret != -ENOIOCTLCMD))
|
||||
if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
|
||||
vpif_dbg(1, debug, "stream off failed in subdev\n");
|
||||
|
||||
return vb2_streamoff(&common->buffer_queue, buftype);
|
||||
}
|
||||
|
||||
/**
|
||||
* vpif_map_sub_device_to_input() - Maps sub device to input
|
||||
* @ch - ptr to channel
|
||||
* @config - ptr to capture configuration
|
||||
* vpif_input_to_subdev() - Maps input to sub device
|
||||
* @vpif_cfg - global config ptr
|
||||
* @chan_cfg - channel config ptr
|
||||
* @input_index - Given input index from application
|
||||
* @sub_device_index - index into sd table
|
||||
*
|
||||
* lookup the sub device information for a given input index.
|
||||
* we report all the inputs to application. inputs table also
|
||||
* has sub device name for the each input
|
||||
*/
|
||||
static struct vpif_subdev_info *vpif_map_sub_device_to_input(
|
||||
struct channel_obj *ch,
|
||||
struct vpif_capture_config *vpif_cfg,
|
||||
int input_index,
|
||||
int *sub_device_index)
|
||||
static int vpif_input_to_subdev(
|
||||
struct vpif_capture_config *vpif_cfg,
|
||||
struct vpif_capture_chan_config *chan_cfg,
|
||||
int input_index)
|
||||
{
|
||||
struct vpif_capture_chan_config *chan_cfg;
|
||||
struct vpif_subdev_info *subdev_info = NULL;
|
||||
const char *subdev_name = NULL;
|
||||
struct vpif_subdev_info *subdev_info;
|
||||
const char *subdev_name;
|
||||
int i;
|
||||
|
||||
vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n");
|
||||
vpif_dbg(2, debug, "vpif_input_to_subdev\n");
|
||||
|
||||
chan_cfg = &vpif_cfg->chan_config[ch->channel_id];
|
||||
|
||||
/**
|
||||
* search through the inputs to find the sub device supporting
|
||||
* the input
|
||||
*/
|
||||
for (i = 0; i < chan_cfg->input_count; i++) {
|
||||
/* For each sub device, loop through input */
|
||||
if (i == input_index) {
|
||||
subdev_name = chan_cfg->inputs[i].subdev_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if reached maximum. return null */
|
||||
if (i == chan_cfg->input_count || (NULL == subdev_name))
|
||||
return subdev_info;
|
||||
subdev_name = chan_cfg->inputs[input_index].subdev_name;
|
||||
if (subdev_name == NULL)
|
||||
return -1;
|
||||
|
||||
/* loop through the sub device list to get the sub device info */
|
||||
for (i = 0; i < vpif_cfg->subdev_count; i++) {
|
||||
subdev_info = &vpif_cfg->subdev_info[i];
|
||||
if (!strcmp(subdev_info->name, subdev_name))
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* vpif_set_input() - Select an input
|
||||
* @vpif_cfg - global config ptr
|
||||
* @ch - channel
|
||||
* @_index - Given input index from application
|
||||
*
|
||||
* Select the given input.
|
||||
*/
|
||||
static int vpif_set_input(
|
||||
struct vpif_capture_config *vpif_cfg,
|
||||
struct channel_obj *ch,
|
||||
int index)
|
||||
{
|
||||
struct vpif_capture_chan_config *chan_cfg =
|
||||
&vpif_cfg->chan_config[ch->channel_id];
|
||||
struct vpif_subdev_info *subdev_info = NULL;
|
||||
struct v4l2_subdev *sd = NULL;
|
||||
u32 input = 0, output = 0;
|
||||
int sd_index;
|
||||
int ret;
|
||||
|
||||
sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index);
|
||||
if (sd_index >= 0) {
|
||||
sd = vpif_obj.sd[sd_index];
|
||||
subdev_info = &vpif_cfg->subdev_info[sd_index];
|
||||
}
|
||||
|
||||
if (i == vpif_cfg->subdev_count)
|
||||
return subdev_info;
|
||||
/* first setup input path from sub device to vpif */
|
||||
if (sd && vpif_cfg->setup_input_path) {
|
||||
ret = vpif_cfg->setup_input_path(ch->channel_id,
|
||||
subdev_info->name);
|
||||
if (ret < 0) {
|
||||
vpif_dbg(1, debug, "couldn't setup input path for the" \
|
||||
" sub device %s, for input index %d\n",
|
||||
subdev_info->name, index);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the sub device is registered */
|
||||
if (NULL == vpif_obj.sd[i])
|
||||
return NULL;
|
||||
if (sd) {
|
||||
input = chan_cfg->inputs[index].input_route;
|
||||
output = chan_cfg->inputs[index].output_route;
|
||||
ret = v4l2_subdev_call(sd, video, s_routing,
|
||||
input, output, 0);
|
||||
if (ret < 0 && ret != -ENOIOCTLCMD) {
|
||||
vpif_dbg(1, debug, "Failed to set input\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ch->input_idx = index;
|
||||
ch->sd = sd;
|
||||
/* copy interface parameters to vpif */
|
||||
ch->vpifparams.iface = chan_cfg->vpif_if;
|
||||
|
||||
*sub_device_index = i;
|
||||
return subdev_info;
|
||||
/* update tvnorms from the sub device input info */
|
||||
ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1324,12 +1339,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
|
|||
vpif_dbg(2, debug, "vpif_querystd\n");
|
||||
|
||||
/* Call querystd function of decoder device */
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
|
||||
querystd, std_id);
|
||||
if (ret < 0)
|
||||
vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
|
||||
ret = v4l2_subdev_call(ch->sd, video, querystd, std_id);
|
||||
|
||||
return ret;
|
||||
if (ret == -ENOIOCTLCMD || ret == -ENODEV)
|
||||
return -ENODATA;
|
||||
if (ret) {
|
||||
vpif_dbg(1, debug, "Failed to query standard for sub devices\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1397,11 +1416,12 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
|
|||
vpif_config_format(ch);
|
||||
|
||||
/* set standard in the sub device */
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
|
||||
s_std, *std_id);
|
||||
if (ret < 0)
|
||||
ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id);
|
||||
if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
|
||||
vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1441,10 +1461,8 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index)
|
|||
{
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
|
||||
*index = vid_ch->input_idx;
|
||||
|
||||
*index = ch->input_idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1461,13 +1479,13 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
|
|||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
struct vpif_subdev_info *subdev_info;
|
||||
int ret = 0, sd_index = 0;
|
||||
u32 input = 0, output = 0;
|
||||
int ret;
|
||||
|
||||
chan_cfg = &config->chan_config[ch->channel_id];
|
||||
|
||||
if (index >= chan_cfg->input_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (common->started) {
|
||||
vpif_err("Streaming in progress\n");
|
||||
return -EBUSY;
|
||||
|
|
@ -1486,45 +1504,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
|
|||
return ret;
|
||||
|
||||
fh->initialized = 1;
|
||||
subdev_info = vpif_map_sub_device_to_input(ch, config, index,
|
||||
&sd_index);
|
||||
if (NULL == subdev_info) {
|
||||
vpif_dbg(1, debug,
|
||||
"couldn't lookup sub device for the input index\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* first setup input path from sub device to vpif */
|
||||
if (config->setup_input_path) {
|
||||
ret = config->setup_input_path(ch->channel_id,
|
||||
subdev_info->name);
|
||||
if (ret < 0) {
|
||||
vpif_dbg(1, debug, "couldn't setup input path for the"
|
||||
" sub device %s, for input index %d\n",
|
||||
subdev_info->name, index);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (subdev_info->can_route) {
|
||||
input = subdev_info->input;
|
||||
output = subdev_info->output;
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing,
|
||||
input, output, 0);
|
||||
if (ret < 0) {
|
||||
vpif_dbg(1, debug, "Failed to set input\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
vid_ch->input_idx = index;
|
||||
ch->curr_subdev_info = subdev_info;
|
||||
ch->curr_sd_index = sd_index;
|
||||
/* copy interface parameters to vpif */
|
||||
ch->vpifparams.iface = subdev_info->vpif_if;
|
||||
|
||||
/* update tvnorms from the sub device input info */
|
||||
ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
|
||||
return ret;
|
||||
return vpif_set_input(config, ch, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1655,9 +1635,11 @@ static int vpif_querycap(struct file *file, void *priv,
|
|||
{
|
||||
struct vpif_capture_config *config = vpif_dev->platform_data;
|
||||
|
||||
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
|
||||
strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
|
||||
strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info));
|
||||
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
|
||||
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
|
||||
snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
|
||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
|
||||
dev_name(vpif_dev));
|
||||
strlcpy(cap->card, config->card_name, sizeof(cap->card));
|
||||
|
||||
return 0;
|
||||
|
|
@ -1730,9 +1712,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
|
|||
{
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
int ret;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
|
||||
video, enum_dv_timings, timings);
|
||||
ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD && ret == -ENODEV)
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1747,9 +1732,12 @@ vpif_query_dv_timings(struct file *file, void *priv,
|
|||
{
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
int ret;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
|
||||
video, query_dv_timings, timings);
|
||||
ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD && ret == -ENODEV)
|
||||
return -ENODATA;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1775,13 +1763,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/* Configure subdevice timings, if any */
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
|
||||
video, s_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD) {
|
||||
vpif_dbg(2, debug, "Custom DV timings not supported by "
|
||||
"subdevice\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD || ret == -ENODEV)
|
||||
ret = 0;
|
||||
if (ret < 0) {
|
||||
vpif_dbg(2, debug, "Error setting custom DV timings\n");
|
||||
return ret;
|
||||
|
|
@ -1906,8 +1890,7 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
|
|||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
|
||||
g_register, reg);
|
||||
return v4l2_subdev_call(ch->sd, core, g_register, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1924,8 +1907,7 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
|
|||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
|
||||
s_register, reg);
|
||||
return v4l2_subdev_call(ch->sd, core, s_register, reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -2063,7 +2045,8 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct vpif_subdev_info *subdevdata;
|
||||
struct vpif_capture_config *config;
|
||||
int i, j, k, m, q, err;
|
||||
int i, j, k, err;
|
||||
int res_idx = 0;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
struct channel_obj *ch;
|
||||
struct common_obj *common;
|
||||
|
|
@ -2086,18 +2069,19 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
k = 0;
|
||||
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
|
||||
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
|
||||
for (i = res->start; i <= res->end; i++) {
|
||||
if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
|
||||
"VPIF_Capture",
|
||||
(void *)(&vpif_obj.dev[k]->channel_id))) {
|
||||
"VPIF_Capture", (void *)
|
||||
(&vpif_obj.dev[res_idx]->channel_id))) {
|
||||
err = -EBUSY;
|
||||
i--;
|
||||
for (j = 0; j < i; j++)
|
||||
free_irq(j, (void *)
|
||||
(&vpif_obj.dev[res_idx]->channel_id));
|
||||
goto vpif_int_err;
|
||||
}
|
||||
}
|
||||
k++;
|
||||
res_idx++;
|
||||
}
|
||||
|
||||
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
|
||||
|
|
@ -2111,7 +2095,7 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
video_device_release(ch->video_dev);
|
||||
}
|
||||
err = -ENOMEM;
|
||||
goto vpif_dev_alloc_err;
|
||||
goto vpif_int_err;
|
||||
}
|
||||
|
||||
/* Initialize field of video device */
|
||||
|
|
@ -2142,24 +2126,6 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
ch->channel_id = j;
|
||||
common = &(ch->common[VPIF_VIDEO_INDEX]);
|
||||
spin_lock_init(&common->irqlock);
|
||||
mutex_init(&common->lock);
|
||||
ch->video_dev->lock = &common->lock;
|
||||
/* Initialize prio member of channel object */
|
||||
v4l2_prio_init(&ch->prio);
|
||||
err = video_register_device(ch->video_dev,
|
||||
VFL_TYPE_GRABBER, (j ? 1 : 0));
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
}
|
||||
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
config = pdev->dev.platform_data;
|
||||
|
||||
|
|
@ -2169,7 +2135,7 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
if (vpif_obj.sd == NULL) {
|
||||
vpif_err("unable to allocate memory for subdevice pointers\n");
|
||||
err = -ENOMEM;
|
||||
goto probe_out;
|
||||
goto vpif_sd_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
|
|
@ -2186,19 +2152,32 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
}
|
||||
v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
|
||||
subdevdata->name);
|
||||
|
||||
if (vpif_obj.sd[i])
|
||||
vpif_obj.sd[i]->grp_id = 1 << i;
|
||||
}
|
||||
|
||||
for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
ch->channel_id = j;
|
||||
common = &(ch->common[VPIF_VIDEO_INDEX]);
|
||||
spin_lock_init(&common->irqlock);
|
||||
mutex_init(&common->lock);
|
||||
ch->video_dev->lock = &common->lock;
|
||||
/* Initialize prio member of channel object */
|
||||
v4l2_prio_init(&ch->prio);
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
/* select input 0 */
|
||||
err = vpif_set_input(config, ch, 0);
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
err = video_register_device(ch->video_dev,
|
||||
VFL_TYPE_GRABBER, (j ? 1 : 0));
|
||||
if (err)
|
||||
goto probe_out;
|
||||
}
|
||||
v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
|
||||
return 0;
|
||||
|
||||
probe_subdev_out:
|
||||
/* free sub devices memory */
|
||||
kfree(vpif_obj.sd);
|
||||
|
||||
j = VPIF_CAPTURE_MAX_DEVICES;
|
||||
probe_out:
|
||||
for (k = 0; k < j; k++) {
|
||||
/* Get the pointer to the channel object */
|
||||
|
|
@ -2206,22 +2185,23 @@ probe_out:
|
|||
/* Unregister video device */
|
||||
video_unregister_device(ch->video_dev);
|
||||
}
|
||||
probe_subdev_out:
|
||||
/* free sub devices memory */
|
||||
kfree(vpif_obj.sd);
|
||||
|
||||
vpif_dev_alloc_err:
|
||||
k = VPIF_CAPTURE_MAX_DEVICES-1;
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
|
||||
i = res->end;
|
||||
|
||||
vpif_int_err:
|
||||
for (q = k; q >= 0; q--) {
|
||||
for (m = i; m >= (int)res->start; m--)
|
||||
free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
|
||||
if (res)
|
||||
i = res->end;
|
||||
vpif_sd_error:
|
||||
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
|
||||
ch = vpif_obj.dev[i];
|
||||
/* Note: does nothing if ch->video_dev == NULL */
|
||||
video_device_release(ch->video_dev);
|
||||
}
|
||||
vpif_int_err:
|
||||
v4l2_device_unregister(&vpif_obj.v4l2_dev);
|
||||
for (i = 0; i < res_idx; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
for (j = res->start; j <= res->end; j++)
|
||||
free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ struct video_obj {
|
|||
/* Currently selected or default standard */
|
||||
v4l2_std_id stdid;
|
||||
struct v4l2_dv_timings dv_timings;
|
||||
/* This is to track the last input that is passed to application */
|
||||
u32 input_idx;
|
||||
};
|
||||
|
||||
struct vpif_cap_buffer {
|
||||
|
|
@ -119,10 +117,10 @@ struct channel_obj {
|
|||
u8 initialized;
|
||||
/* Identifies channel */
|
||||
enum vpif_channel_id channel_id;
|
||||
/* index into sd table */
|
||||
int curr_sd_index;
|
||||
/* ptr to current sub device information */
|
||||
struct vpif_subdev_info *curr_subdev_info;
|
||||
/* Current input */
|
||||
u32 input_idx;
|
||||
/* subdev corresponding to the current input, may be NULL */
|
||||
struct v4l2_subdev *sd;
|
||||
/* vpif configuration params */
|
||||
struct vpif_params vpifparams;
|
||||
/* common object array */
|
||||
|
|
@ -159,10 +157,6 @@ struct vpif_config_params {
|
|||
u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
|
||||
u8 max_device_type;
|
||||
};
|
||||
/* Struct which keeps track of the line numbers for the sliced vbi service */
|
||||
struct vpif_service_line {
|
||||
u16 service_id;
|
||||
u16 service_line[2];
|
||||
};
|
||||
|
||||
#endif /* End of __KERNEL__ */
|
||||
#endif /* VPIF_CAPTURE_H */
|
||||
|
|
|
|||
|
|
@ -280,12 +280,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
}
|
||||
|
||||
/* clock settings */
|
||||
ret =
|
||||
vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode,
|
||||
ch->vpifparams.std_info.hd_sd);
|
||||
if (ret < 0) {
|
||||
vpif_err("can't set clock\n");
|
||||
return ret;
|
||||
if (vpif_config_data->set_clock) {
|
||||
ret = vpif_config_data->set_clock(ch->vpifparams.std_info.
|
||||
ycmux_mode, ch->vpifparams.std_info.hd_sd);
|
||||
if (ret < 0) {
|
||||
vpif_err("can't set clock\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* set the parameters and addresses */
|
||||
|
|
@ -307,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
channel2_intr_assert();
|
||||
channel2_intr_enable(1);
|
||||
enable_channel2(1);
|
||||
if (vpif_config_data->ch2_clip_en)
|
||||
if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
|
||||
channel2_clipping_enable(1);
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
channel3_intr_assert();
|
||||
channel3_intr_enable(1);
|
||||
enable_channel3(1);
|
||||
if (vpif_config_data->ch3_clip_en)
|
||||
if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
|
||||
channel3_clipping_enable(1);
|
||||
}
|
||||
|
||||
|
|
@ -826,9 +827,11 @@ static int vpif_querycap(struct file *file, void *priv,
|
|||
{
|
||||
struct vpif_display_config *config = vpif_dev->platform_data;
|
||||
|
||||
cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
|
||||
strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
|
||||
strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
|
||||
cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
|
||||
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
|
||||
snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
|
||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
|
||||
dev_name(vpif_dev));
|
||||
strlcpy(cap->card, config->card_name, sizeof(cap->card));
|
||||
|
||||
return 0;
|
||||
|
|
@ -935,6 +938,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
|
|||
enum v4l2_field field;
|
||||
struct vb2_queue *q;
|
||||
u8 index = 0;
|
||||
int ret;
|
||||
|
||||
/* This file handle has not initialized the channel,
|
||||
It is not allowed to do settings */
|
||||
|
|
@ -980,8 +984,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
|
|||
q->mem_ops = &vb2_dma_contig_memops;
|
||||
q->buf_struct_size = sizeof(struct vpif_disp_buffer);
|
||||
|
||||
vb2_queue_init(q);
|
||||
|
||||
ret = vb2_queue_init(q);
|
||||
if (ret) {
|
||||
vpif_err("vpif_display: vb2_queue_init() failed\n");
|
||||
vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
|
||||
return ret;
|
||||
}
|
||||
/* Set io allowed member of file handle to TRUE */
|
||||
fh->io_allowed[index] = 1;
|
||||
/* Increment io usrs member of channel object to 1 */
|
||||
|
|
@ -1173,14 +1181,16 @@ static int vpif_streamoff(struct file *file, void *priv,
|
|||
if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
|
||||
/* disable channel */
|
||||
if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
|
||||
if (vpif_config_data->ch2_clip_en)
|
||||
if (vpif_config_data->
|
||||
chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
|
||||
channel2_clipping_enable(0);
|
||||
enable_channel2(0);
|
||||
channel2_intr_enable(0);
|
||||
}
|
||||
if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
|
||||
(2 == common->started)) {
|
||||
if (vpif_config_data->ch3_clip_en)
|
||||
if (vpif_config_data->
|
||||
chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
|
||||
channel3_clipping_enable(0);
|
||||
enable_channel3(0);
|
||||
channel3_intr_enable(0);
|
||||
|
|
@ -1213,49 +1223,126 @@ static int vpif_enum_output(struct file *file, void *fh,
|
|||
{
|
||||
|
||||
struct vpif_display_config *config = vpif_dev->platform_data;
|
||||
struct vpif_display_chan_config *chan_cfg;
|
||||
struct vpif_fh *vpif_handler = fh;
|
||||
struct channel_obj *ch = vpif_handler->channel;
|
||||
|
||||
if (output->index >= config->output_count) {
|
||||
chan_cfg = &config->chan_config[ch->channel_id];
|
||||
if (output->index >= chan_cfg->output_count) {
|
||||
vpif_dbg(1, debug, "Invalid output index\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
strcpy(output->name, config->output[output->index]);
|
||||
output->type = V4L2_OUTPUT_TYPE_ANALOG;
|
||||
output->std = VPIF_V4L2_STD;
|
||||
*output = chan_cfg->outputs[output->index].output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vpif_output_to_subdev() - Maps output to sub device
|
||||
* @vpif_cfg - global config ptr
|
||||
* @chan_cfg - channel config ptr
|
||||
* @index - Given output index from application
|
||||
*
|
||||
* lookup the sub device information for a given output index.
|
||||
* we report all the output to application. output table also
|
||||
* has sub device name for the each output
|
||||
*/
|
||||
static int
|
||||
vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,
|
||||
struct vpif_display_chan_config *chan_cfg, int index)
|
||||
{
|
||||
struct vpif_subdev_info *subdev_info;
|
||||
const char *subdev_name;
|
||||
int i;
|
||||
|
||||
vpif_dbg(2, debug, "vpif_output_to_subdev\n");
|
||||
|
||||
if (chan_cfg->outputs == NULL)
|
||||
return -1;
|
||||
|
||||
subdev_name = chan_cfg->outputs[index].subdev_name;
|
||||
if (subdev_name == NULL)
|
||||
return -1;
|
||||
|
||||
/* loop through the sub device list to get the sub device info */
|
||||
for (i = 0; i < vpif_cfg->subdev_count; i++) {
|
||||
subdev_info = &vpif_cfg->subdevinfo[i];
|
||||
if (!strcmp(subdev_info->name, subdev_name))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* vpif_set_output() - Select an output
|
||||
* @vpif_cfg - global config ptr
|
||||
* @ch - channel
|
||||
* @index - Given output index from application
|
||||
*
|
||||
* Select the given output.
|
||||
*/
|
||||
static int vpif_set_output(struct vpif_display_config *vpif_cfg,
|
||||
struct channel_obj *ch, int index)
|
||||
{
|
||||
struct vpif_display_chan_config *chan_cfg =
|
||||
&vpif_cfg->chan_config[ch->channel_id];
|
||||
struct vpif_subdev_info *subdev_info = NULL;
|
||||
struct v4l2_subdev *sd = NULL;
|
||||
u32 input = 0, output = 0;
|
||||
int sd_index;
|
||||
int ret;
|
||||
|
||||
sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);
|
||||
if (sd_index >= 0) {
|
||||
sd = vpif_obj.sd[sd_index];
|
||||
subdev_info = &vpif_cfg->subdevinfo[sd_index];
|
||||
}
|
||||
|
||||
if (sd) {
|
||||
input = chan_cfg->outputs[index].input_route;
|
||||
output = chan_cfg->outputs[index].output_route;
|
||||
ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
|
||||
if (ret < 0 && ret != -ENOIOCTLCMD) {
|
||||
vpif_err("Failed to set output\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
ch->output_idx = index;
|
||||
ch->sd = sd;
|
||||
if (chan_cfg->outputs != NULL)
|
||||
/* update tvnorms from the sub device output info */
|
||||
ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vpif_s_output(struct file *file, void *priv, unsigned int i)
|
||||
{
|
||||
struct vpif_display_config *config = vpif_dev->platform_data;
|
||||
struct vpif_display_chan_config *chan_cfg;
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
|
||||
int ret = 0;
|
||||
|
||||
chan_cfg = &config->chan_config[ch->channel_id];
|
||||
|
||||
if (i >= chan_cfg->output_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (common->started) {
|
||||
vpif_err("Streaming in progress\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
|
||||
s_routing, 0, i, 0);
|
||||
|
||||
if (ret < 0)
|
||||
vpif_err("Failed to set output standard\n");
|
||||
|
||||
vid_ch->output_id = i;
|
||||
return ret;
|
||||
return vpif_set_output(config, ch, i);
|
||||
}
|
||||
|
||||
static int vpif_g_output(struct file *file, void *priv, unsigned int *i)
|
||||
{
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
|
||||
*i = vid_ch->output_id;
|
||||
*i = ch->output_idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1290,10 +1377,12 @@ vpif_enum_dv_timings(struct file *file, void *priv,
|
|||
{
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
int ret;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
|
||||
video, enum_dv_timings, timings);
|
||||
ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD && ret == -ENODEV)
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1319,13 +1408,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
/* Configure subdevice timings, if any */
|
||||
ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
|
||||
video, s_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD) {
|
||||
vpif_dbg(2, debug, "Custom DV timings not supported by "
|
||||
"subdevice\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
|
||||
if (ret == -ENOIOCTLCMD || ret == -ENODEV)
|
||||
ret = 0;
|
||||
if (ret < 0) {
|
||||
vpif_dbg(2, debug, "Error setting custom DV timings\n");
|
||||
return ret;
|
||||
|
|
@ -1450,10 +1535,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
|
|||
struct v4l2_dbg_register *reg){
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
|
||||
g_register, reg);
|
||||
return v4l2_subdev_call(ch->sd, core, g_register, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1469,10 +1552,8 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
|
|||
struct v4l2_dbg_register *reg){
|
||||
struct vpif_fh *fh = priv;
|
||||
struct channel_obj *ch = fh->channel;
|
||||
struct video_obj *vid_ch = &ch->video;
|
||||
|
||||
return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
|
||||
s_register, reg);
|
||||
return v4l2_subdev_call(ch->sd, core, s_register, reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1536,9 +1617,6 @@ static struct video_device vpif_video_template = {
|
|||
.name = "vpif",
|
||||
.fops = &vpif_fops,
|
||||
.ioctl_ops = &vpif_ioctl_ops,
|
||||
.tvnorms = VPIF_V4L2_STD,
|
||||
.current_norm = V4L2_STD_625_50,
|
||||
|
||||
};
|
||||
|
||||
/*Configure the channels, buffer sizei, request irq */
|
||||
|
|
@ -1611,7 +1689,8 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct vpif_subdev_info *subdevdata;
|
||||
struct vpif_display_config *config;
|
||||
int i, j = 0, k, q, m, err = 0;
|
||||
int i, j = 0, k, err = 0;
|
||||
int res_idx = 0;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
struct common_obj *common;
|
||||
struct channel_obj *ch;
|
||||
|
|
@ -1634,21 +1713,22 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
k = 0;
|
||||
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
|
||||
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
|
||||
for (i = res->start; i <= res->end; i++) {
|
||||
if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
|
||||
"VPIF_Display",
|
||||
(void *)(&vpif_obj.dev[k]->channel_id))) {
|
||||
"VPIF_Display", (void *)
|
||||
(&vpif_obj.dev[res_idx]->channel_id))) {
|
||||
err = -EBUSY;
|
||||
for (j = 0; j < i; j++)
|
||||
free_irq(j, (void *)
|
||||
(&vpif_obj.dev[res_idx]->channel_id));
|
||||
goto vpif_int_err;
|
||||
}
|
||||
}
|
||||
k++;
|
||||
res_idx++;
|
||||
}
|
||||
|
||||
for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
|
||||
|
||||
/* Get the pointer to the channel object */
|
||||
ch = vpif_obj.dev[i];
|
||||
|
||||
|
|
@ -1694,6 +1774,32 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
config = pdev->dev.platform_data;
|
||||
subdev_count = config->subdev_count;
|
||||
subdevdata = config->subdevinfo;
|
||||
vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
|
||||
GFP_KERNEL);
|
||||
if (vpif_obj.sd == NULL) {
|
||||
vpif_err("unable to allocate memory for subdevice pointers\n");
|
||||
err = -ENOMEM;
|
||||
goto vpif_sd_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
|
||||
i2c_adap,
|
||||
&subdevdata[i].board_info,
|
||||
NULL);
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
|
||||
if (vpif_obj.sd[i])
|
||||
vpif_obj.sd[i]->grp_id = 1 << i;
|
||||
}
|
||||
|
||||
for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
/* Initialize field of the channel objects */
|
||||
|
|
@ -1715,6 +1821,8 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
|
||||
}
|
||||
ch->initialized = 0;
|
||||
if (subdev_count)
|
||||
ch->sd = vpif_obj.sd[0];
|
||||
ch->channel_id = j;
|
||||
if (j < 2)
|
||||
ch->common[VPIF_VIDEO_INDEX].numbuffers =
|
||||
|
|
@ -1729,6 +1837,12 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
ch->common[VPIF_VIDEO_INDEX].fmt.type =
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
||||
ch->video_dev->lock = &common->lock;
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
/* select output 0 */
|
||||
err = vpif_set_output(config, ch, 0);
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
/* register video device */
|
||||
vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
|
||||
|
|
@ -1738,42 +1852,12 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
VFL_TYPE_GRABBER, (j ? 3 : 2));
|
||||
if (err < 0)
|
||||
goto probe_out;
|
||||
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
}
|
||||
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
config = pdev->dev.platform_data;
|
||||
subdev_count = config->subdev_count;
|
||||
subdevdata = config->subdevinfo;
|
||||
vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
|
||||
GFP_KERNEL);
|
||||
if (vpif_obj.sd == NULL) {
|
||||
vpif_err("unable to allocate memory for subdevice pointers\n");
|
||||
err = -ENOMEM;
|
||||
goto probe_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
|
||||
i2c_adap,
|
||||
&subdevdata[i].board_info,
|
||||
NULL);
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
|
||||
if (vpif_obj.sd[i])
|
||||
vpif_obj.sd[i]->grp_id = 1 << i;
|
||||
}
|
||||
|
||||
v4l2_info(&vpif_obj.v4l2_dev,
|
||||
" VPIF display driver initialized\n");
|
||||
return 0;
|
||||
|
||||
probe_subdev_out:
|
||||
kfree(vpif_obj.sd);
|
||||
probe_out:
|
||||
for (k = 0; k < j; k++) {
|
||||
ch = vpif_obj.dev[k];
|
||||
|
|
@ -1781,14 +1865,21 @@ probe_out:
|
|||
video_device_release(ch->video_dev);
|
||||
ch->video_dev = NULL;
|
||||
}
|
||||
probe_subdev_out:
|
||||
kfree(vpif_obj.sd);
|
||||
vpif_sd_error:
|
||||
for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
|
||||
ch = vpif_obj.dev[i];
|
||||
/* Note: does nothing if ch->video_dev == NULL */
|
||||
video_device_release(ch->video_dev);
|
||||
}
|
||||
vpif_int_err:
|
||||
v4l2_device_unregister(&vpif_obj.v4l2_dev);
|
||||
vpif_err("VPIF IRQ request failed\n");
|
||||
for (q = k; k >= 0; k--) {
|
||||
for (m = i; m >= res->start; m--)
|
||||
free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
|
||||
m = res->end;
|
||||
for (i = 0; i < res_idx; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
for (j = res->start; j <= res->end; j++)
|
||||
free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -62,13 +62,6 @@ struct video_obj {
|
|||
v4l2_std_id stdid; /* Currently selected or default
|
||||
* standard */
|
||||
struct v4l2_dv_timings dv_timings;
|
||||
u32 output_id; /* Current output id */
|
||||
};
|
||||
|
||||
struct vbi_obj {
|
||||
int num_services;
|
||||
struct vpif_vbi_params vbiparams; /* vpif parameters for the raw
|
||||
* vbi data */
|
||||
};
|
||||
|
||||
struct vpif_disp_buffer {
|
||||
|
|
@ -131,12 +124,13 @@ struct channel_obj {
|
|||
* which is being displayed */
|
||||
u8 initialized; /* flag to indicate whether
|
||||
* encoder is initialized */
|
||||
u32 output_idx; /* Current output index */
|
||||
struct v4l2_subdev *sd; /* Current output subdev(may be NULL) */
|
||||
|
||||
enum vpif_channel_id channel_id;/* Identifies channel */
|
||||
struct vpif_params vpifparams;
|
||||
struct common_obj common[VPIF_NUMOBJECTS];
|
||||
struct video_obj video;
|
||||
struct vbi_obj vbi;
|
||||
};
|
||||
|
||||
/* File handle structure */
|
||||
|
|
@ -168,12 +162,4 @@ struct vpif_config_params {
|
|||
u8 min_numbuffers;
|
||||
};
|
||||
|
||||
/* Struct which keeps track of the line numbers for the sliced vbi service */
|
||||
struct vpif_service_line {
|
||||
u16 service_id;
|
||||
u16 service_line[2];
|
||||
u16 enc_service_id;
|
||||
u8 bytestowrite;
|
||||
};
|
||||
|
||||
#endif /* DAVINCIHD_DISPLAY_H */
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
|
|||
else
|
||||
cfg |= GSC_IN_YUV422_3P;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
writel(cfg, dev->regs + GSC_IN_CON);
|
||||
}
|
||||
|
|
@ -332,7 +332,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
|
|||
case 3:
|
||||
cfg |= GSC_OUT_YUV420_3P;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
end_set:
|
||||
writel(cfg, dev->regs + GSC_OUT_CON);
|
||||
|
|
|
|||
|
|
@ -864,7 +864,7 @@ int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *
|
|||
{
|
||||
struct viu_fh *fh = priv;
|
||||
struct viu_dev *dev = fh->dev;
|
||||
struct v4l2_framebuffer *fb = arg;
|
||||
const struct v4l2_framebuffer *fb = arg;
|
||||
struct viu_fmt *fmt;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
|
||||
|
|
|
|||
|
|
@ -397,8 +397,7 @@ static void device_isr(unsigned long priv)
|
|||
curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
|
||||
|
||||
if (NULL == curr_ctx) {
|
||||
printk(KERN_ERR
|
||||
"Instance released before the end of transaction\n");
|
||||
pr_err("Instance released before the end of transaction\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -894,7 +893,7 @@ static int m2mtest_open(struct file *file)
|
|||
|
||||
if (mutex_lock_interruptible(&dev->dev_mutex))
|
||||
return -ERESTARTSYS;
|
||||
ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
rc = -ENOMEM;
|
||||
goto open_unlock;
|
||||
|
|
@ -1020,7 +1019,7 @@ static int m2mtest_probe(struct platform_device *pdev)
|
|||
struct video_device *vfd;
|
||||
int ret;
|
||||
|
||||
dev = kzalloc(sizeof *dev, GFP_KERNEL);
|
||||
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1028,7 +1027,7 @@ static int m2mtest_probe(struct platform_device *pdev)
|
|||
|
||||
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
|
||||
if (ret)
|
||||
goto free_dev;
|
||||
return ret;
|
||||
|
||||
atomic_set(&dev->num_inst, 0);
|
||||
mutex_init(&dev->dev_mutex);
|
||||
|
|
@ -1067,15 +1066,13 @@ static int m2mtest_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
v4l2_m2m_release(dev->m2m_dev);
|
||||
err_m2m:
|
||||
v4l2_m2m_release(dev->m2m_dev);
|
||||
video_unregister_device(dev->vfd);
|
||||
rel_vdev:
|
||||
video_device_release(vfd);
|
||||
unreg_dev:
|
||||
v4l2_device_unregister(&dev->v4l2_dev);
|
||||
free_dev:
|
||||
kfree(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1090,7 +1087,6 @@ static int m2mtest_remove(struct platform_device *pdev)
|
|||
del_timer_sync(&dev->timer);
|
||||
video_unregister_device(dev->vfd);
|
||||
v4l2_device_unregister(&dev->v4l2_dev);
|
||||
kfree(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@
|
|||
#ifndef OMAP3_ISP_REG_H
|
||||
#define OMAP3_ISP_REG_H
|
||||
|
||||
#include <plat/omap34xx.h>
|
||||
|
||||
|
||||
#define CM_CAM_MCLK_HZ 172800000 /* Hz */
|
||||
|
||||
/* ISP Submodules offset */
|
||||
|
||||
#define L4_34XX_BASE 0x48000000
|
||||
#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000)
|
||||
|
||||
#define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
|
||||
#define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
|
||||
|
||||
|
|
|
|||
|
|
@ -177,7 +177,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
|
|||
|
||||
void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
|
||||
{
|
||||
struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
|
||||
struct fimc_vid_cap *cap = &fimc->vid_cap;
|
||||
struct fimc_frame *f = &cap->ctx->d_frame;
|
||||
struct fimc_vid_buffer *v_buf;
|
||||
struct timeval *tv;
|
||||
struct timespec ts;
|
||||
|
|
@ -216,6 +218,25 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
|
|||
if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
|
||||
cap->buf_index = 0;
|
||||
}
|
||||
/*
|
||||
* Set up a buffer at MIPI-CSIS if current image format
|
||||
* requires the frame embedded data capture.
|
||||
*/
|
||||
if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
|
||||
unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
|
||||
unsigned int size = f->payload[plane];
|
||||
s32 index = fimc_hw_get_frame_index(fimc);
|
||||
void *vaddr;
|
||||
|
||||
list_for_each_entry(v_buf, &cap->active_buf_q, list) {
|
||||
if (v_buf->index != index)
|
||||
continue;
|
||||
vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
|
||||
v4l2_subdev_call(csis, video, s_rx_buffer,
|
||||
vaddr, &size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cap->active_buf_cnt == 0) {
|
||||
if (deq_buf)
|
||||
|
|
@ -351,6 +372,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
|
|||
unsigned int size = (wh * fmt->depth[i]) / 8;
|
||||
if (pixm)
|
||||
sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
|
||||
else if (fimc_fmt_is_user_defined(fmt->color))
|
||||
sizes[i] = frame->payload[i];
|
||||
else
|
||||
sizes[i] = max_t(u32, size, frame->payload[i]);
|
||||
|
||||
|
|
@ -611,10 +634,10 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
|
|||
u32 mask = FMT_FLAGS_CAM;
|
||||
struct fimc_fmt *ffmt;
|
||||
|
||||
/* Color conversion from/to JPEG is not supported */
|
||||
/* Conversion from/to JPEG or User Defined format is not supported */
|
||||
if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
|
||||
fimc_fmt_is_jpeg(ctx->s_frame.fmt->color))
|
||||
*code = V4L2_MBUS_FMT_JPEG_1X8;
|
||||
fimc_fmt_is_user_defined(ctx->s_frame.fmt->color))
|
||||
*code = ctx->s_frame.fmt->mbus_code;
|
||||
|
||||
if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
|
||||
mask |= FMT_FLAGS_M2M;
|
||||
|
|
@ -628,18 +651,19 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
|
|||
*fourcc = ffmt->fourcc;
|
||||
|
||||
if (pad == FIMC_SD_PAD_SINK) {
|
||||
max_w = fimc_fmt_is_jpeg(ffmt->color) ?
|
||||
max_w = fimc_fmt_is_user_defined(ffmt->color) ?
|
||||
pl->scaler_dis_w : pl->scaler_en_w;
|
||||
/* Apply the camera input interface pixel constraints */
|
||||
v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
|
||||
height, max_t(u32, *height, 32),
|
||||
FIMC_CAMIF_MAX_HEIGHT,
|
||||
fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1,
|
||||
fimc_fmt_is_user_defined(ffmt->color) ?
|
||||
3 : 1,
|
||||
0);
|
||||
return ffmt;
|
||||
}
|
||||
/* Can't scale or crop in transparent (JPEG) transfer mode */
|
||||
if (fimc_fmt_is_jpeg(ffmt->color)) {
|
||||
if (fimc_fmt_is_user_defined(ffmt->color)) {
|
||||
*width = ctx->s_frame.f_width;
|
||||
*height = ctx->s_frame.f_height;
|
||||
return ffmt;
|
||||
|
|
@ -684,7 +708,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx,
|
|||
u32 max_sc_h, max_sc_v;
|
||||
|
||||
/* In JPEG transparent transfer mode cropping is not supported */
|
||||
if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) {
|
||||
if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) {
|
||||
r->width = sink->f_width;
|
||||
r->height = sink->f_height;
|
||||
r->left = r->top = 0;
|
||||
|
|
@ -847,6 +871,48 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters
|
||||
* @sensor: pointer to the sensor subdev
|
||||
* @plane_fmt: provides plane sizes corresponding to the frame layout entries
|
||||
* @try: true to set the frame parameters, false to query only
|
||||
*
|
||||
* This function is used by this driver only for compressed/blob data formats.
|
||||
*/
|
||||
static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
|
||||
struct v4l2_plane_pix_format *plane_fmt,
|
||||
unsigned int num_planes, bool try)
|
||||
{
|
||||
struct v4l2_mbus_frame_desc fd;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < num_planes; i++)
|
||||
fd.entry[i].length = plane_fmt[i].sizeimage;
|
||||
|
||||
if (try)
|
||||
ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd);
|
||||
else
|
||||
ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (num_planes != fd.num_entries)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < num_planes; i++)
|
||||
plane_fmt[i].sizeimage = fd.entry[i].length;
|
||||
|
||||
if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) {
|
||||
v4l2_err(sensor->v4l2_dev, "Unsupported buffer size: %u\n",
|
||||
fd.entry[0].length);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
|
|
@ -865,7 +931,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
|
|||
struct v4l2_mbus_framefmt mf;
|
||||
struct fimc_fmt *ffmt = NULL;
|
||||
|
||||
if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
|
||||
if (fimc_jpeg_fourcc(pix->pixelformat)) {
|
||||
fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SINK);
|
||||
|
|
@ -879,25 +945,32 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
|
|||
return -EINVAL;
|
||||
|
||||
if (!fimc->vid_cap.user_subdev_api) {
|
||||
mf.width = pix->width;
|
||||
mf.width = pix->width;
|
||||
mf.height = pix->height;
|
||||
mf.code = ffmt->mbus_code;
|
||||
mf.code = ffmt->mbus_code;
|
||||
fimc_md_graph_lock(fimc);
|
||||
fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
|
||||
fimc_md_graph_unlock(fimc);
|
||||
|
||||
pix->width = mf.width;
|
||||
pix->height = mf.height;
|
||||
pix->width = mf.width;
|
||||
pix->height = mf.height;
|
||||
if (ffmt)
|
||||
pix->pixelformat = ffmt->fourcc;
|
||||
}
|
||||
|
||||
fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
|
||||
|
||||
if (ffmt->flags & FMT_FLAGS_COMPRESSED)
|
||||
fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
|
||||
pix->plane_fmt, ffmt->memplanes, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg)
|
||||
static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
|
||||
enum fimc_color_fmt color)
|
||||
{
|
||||
bool jpeg = fimc_fmt_is_user_defined(color);
|
||||
|
||||
ctx->scaler.enabled = !jpeg;
|
||||
fimc_ctrls_activate(ctx, !jpeg);
|
||||
|
||||
|
|
@ -920,7 +993,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
|
|||
return -EBUSY;
|
||||
|
||||
/* Pre-configure format at camera interface input, for JPEG only */
|
||||
if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
|
||||
if (fimc_jpeg_fourcc(pix->pixelformat)) {
|
||||
fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SINK);
|
||||
|
|
@ -953,7 +1026,16 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
|
|||
}
|
||||
|
||||
fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
|
||||
for (i = 0; i < ff->fmt->colplanes; i++)
|
||||
|
||||
if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
|
||||
ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
|
||||
pix->plane_fmt, ff->fmt->memplanes,
|
||||
true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ff->fmt->memplanes; i++)
|
||||
ff->payload[i] = pix->plane_fmt[i].sizeimage;
|
||||
|
||||
set_frame_bounds(ff, pix->width, pix->height);
|
||||
|
|
@ -961,7 +1043,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
|
|||
if (!(ctx->state & FIMC_COMPOSE))
|
||||
set_frame_crop(ff, 0, 0, pix->width, pix->height);
|
||||
|
||||
fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color));
|
||||
fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
|
||||
|
||||
/* Reset cropping and set format at the camera interface input */
|
||||
if (!fimc->vid_cap.user_subdev_api) {
|
||||
|
|
@ -1063,6 +1145,23 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
|
|||
src_fmt.format.height != sink_fmt.format.height ||
|
||||
src_fmt.format.code != sink_fmt.format.code)
|
||||
return -EPIPE;
|
||||
|
||||
if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
|
||||
fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
|
||||
struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
|
||||
struct fimc_frame *frame = &vid_cap->ctx->d_frame;
|
||||
unsigned int i;
|
||||
|
||||
ret = fimc_get_sensor_frame_desc(sd, plane_fmt,
|
||||
frame->fmt->memplanes,
|
||||
false);
|
||||
if (ret < 0)
|
||||
return -EPIPE;
|
||||
|
||||
for (i = 0; i < frame->fmt->memplanes; i++)
|
||||
if (frame->payload[i] < plane_fmt[i].sizeimage)
|
||||
return -EPIPE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1424,7 +1523,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
|
|||
/* Update RGB Alpha control state and value range */
|
||||
fimc_alpha_ctrl_update(ctx);
|
||||
|
||||
fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
|
||||
fimc_capture_mark_jpeg_xfer(ctx, ffmt->color);
|
||||
|
||||
ff = fmt->pad == FIMC_SD_PAD_SINK ?
|
||||
&ctx->s_frame : &ctx->d_frame;
|
||||
|
|
|
|||
|
|
@ -184,7 +184,17 @@ static struct fimc_fmt fimc_formats[] = {
|
|||
.memplanes = 1,
|
||||
.colplanes = 1,
|
||||
.mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
|
||||
.flags = FMT_FLAGS_CAM,
|
||||
.flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
|
||||
}, {
|
||||
.name = "S5C73MX interleaved UYVY/JPEG",
|
||||
.fourcc = V4L2_PIX_FMT_S5C_UYVY_JPG,
|
||||
.color = FIMC_FMT_YUYV_JPEG,
|
||||
.depth = { 8 },
|
||||
.memplanes = 2,
|
||||
.colplanes = 1,
|
||||
.mdataplanes = 0x2, /* plane 1 holds frame meta data */
|
||||
.mbus_code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
|
||||
.flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -371,7 +381,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
} else if (!frame->fmt->mdataplanes) {
|
||||
if (frame->fmt->memplanes >= 2)
|
||||
paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
|
||||
|
||||
|
|
@ -698,6 +708,11 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
|
|||
if (frame->fmt->colplanes == 1) /* packed formats */
|
||||
bpl = (bpl * frame->fmt->depth[0]) / 8;
|
||||
pixm->plane_fmt[i].bytesperline = bpl;
|
||||
|
||||
if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) {
|
||||
pixm->plane_fmt[i].sizeimage = frame->payload[i];
|
||||
continue;
|
||||
}
|
||||
pixm->plane_fmt[i].sizeimage = (frame->o_width *
|
||||
frame->o_height * frame->fmt->depth[i]) / 8;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
#define SCALER_MAX_VRATIO 64
|
||||
#define DMA_MIN_SIZE 8
|
||||
#define FIMC_CAMIF_MAX_HEIGHT 0x2000
|
||||
#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
|
||||
#define FIMC_MAX_PLANES 3
|
||||
|
||||
/* indices to the clocks array */
|
||||
enum {
|
||||
|
|
@ -83,7 +85,7 @@ enum fimc_datapath {
|
|||
};
|
||||
|
||||
enum fimc_color_fmt {
|
||||
FIMC_FMT_RGB444 = 0x10,
|
||||
FIMC_FMT_RGB444 = 0x10,
|
||||
FIMC_FMT_RGB555,
|
||||
FIMC_FMT_RGB565,
|
||||
FIMC_FMT_RGB666,
|
||||
|
|
@ -95,14 +97,15 @@ enum fimc_color_fmt {
|
|||
FIMC_FMT_CBYCRY422,
|
||||
FIMC_FMT_CRYCBY422,
|
||||
FIMC_FMT_YCBCR444_LOCAL,
|
||||
FIMC_FMT_JPEG = 0x40,
|
||||
FIMC_FMT_RAW8 = 0x80,
|
||||
FIMC_FMT_RAW8 = 0x40,
|
||||
FIMC_FMT_RAW10,
|
||||
FIMC_FMT_RAW12,
|
||||
FIMC_FMT_JPEG = 0x80,
|
||||
FIMC_FMT_YUYV_JPEG = 0x100,
|
||||
};
|
||||
|
||||
#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180))
|
||||
#define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
|
||||
#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
|
||||
|
||||
#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
|
||||
__strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
|
||||
|
|
@ -139,6 +142,7 @@ enum fimc_color_fmt {
|
|||
* @memplanes: number of physically non-contiguous data planes
|
||||
* @colplanes: number of physically contiguous data planes
|
||||
* @depth: per plane driver's private 'number of bits per pixel'
|
||||
* @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no)
|
||||
* @flags: flags indicating which operation mode format applies to
|
||||
*/
|
||||
struct fimc_fmt {
|
||||
|
|
@ -149,12 +153,14 @@ struct fimc_fmt {
|
|||
u16 memplanes;
|
||||
u16 colplanes;
|
||||
u8 depth[VIDEO_MAX_PLANES];
|
||||
u16 mdataplanes;
|
||||
u16 flags;
|
||||
#define FMT_FLAGS_CAM (1 << 0)
|
||||
#define FMT_FLAGS_M2M_IN (1 << 1)
|
||||
#define FMT_FLAGS_M2M_OUT (1 << 2)
|
||||
#define FMT_FLAGS_M2M (1 << 1 | 1 << 2)
|
||||
#define FMT_HAS_ALPHA (1 << 3)
|
||||
#define FMT_FLAGS_COMPRESSED (1 << 4)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -272,7 +278,7 @@ struct fimc_frame {
|
|||
u32 offs_v;
|
||||
u32 width;
|
||||
u32 height;
|
||||
unsigned long payload[VIDEO_MAX_PLANES];
|
||||
unsigned int payload[VIDEO_MAX_PLANES];
|
||||
struct fimc_addr paddr;
|
||||
struct fimc_dma_offset dma_offset;
|
||||
struct fimc_fmt *fmt;
|
||||
|
|
@ -577,6 +583,18 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
|
|||
return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
|
||||
}
|
||||
|
||||
static inline bool fimc_jpeg_fourcc(u32 pixelformat)
|
||||
{
|
||||
return (pixelformat == V4L2_PIX_FMT_JPEG ||
|
||||
pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG);
|
||||
}
|
||||
|
||||
static inline bool fimc_user_defined_mbus_fmt(u32 code)
|
||||
{
|
||||
return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
|
||||
code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
|
||||
}
|
||||
|
||||
/* Return the alpha component bit mask */
|
||||
static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -551,30 +551,31 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr)
|
||||
static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
|
||||
{
|
||||
struct fimc_ctx *ctx = fh_to_ctx(fh);
|
||||
struct fimc_dev *fimc = ctx->fimc_dev;
|
||||
struct v4l2_crop cr = *crop;
|
||||
struct fimc_frame *f;
|
||||
int ret;
|
||||
|
||||
ret = fimc_m2m_try_crop(ctx, cr);
|
||||
ret = fimc_m2m_try_crop(ctx, &cr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
|
||||
f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
|
||||
&ctx->s_frame : &ctx->d_frame;
|
||||
|
||||
/* Check to see if scaling ratio is within supported range */
|
||||
if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
|
||||
if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
ret = fimc_check_scaler_ratio(ctx, cr->c.width,
|
||||
cr->c.height, ctx->d_frame.width,
|
||||
if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
ret = fimc_check_scaler_ratio(ctx, cr.c.width,
|
||||
cr.c.height, ctx->d_frame.width,
|
||||
ctx->d_frame.height, ctx->rotation);
|
||||
} else {
|
||||
ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
|
||||
ctx->s_frame.height, cr->c.width,
|
||||
cr->c.height, ctx->rotation);
|
||||
ctx->s_frame.height, cr.c.width,
|
||||
cr.c.height, ctx->rotation);
|
||||
}
|
||||
if (ret) {
|
||||
v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
|
||||
|
|
@ -582,10 +583,10 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *
|
|||
}
|
||||
}
|
||||
|
||||
f->offs_h = cr->c.left;
|
||||
f->offs_v = cr->c.top;
|
||||
f->width = cr->c.width;
|
||||
f->height = cr->c.height;
|
||||
f->offs_h = cr.c.left;
|
||||
f->offs_v = cr.c.top;
|
||||
f->width = cr.c.width;
|
||||
f->height = cr.c.height;
|
||||
|
||||
fimc_ctx_state_set(FIMC_PARAMS, ctx);
|
||||
|
||||
|
|
|
|||
|
|
@ -625,7 +625,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
|
|||
cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
|
||||
} /* else defaults to ITU-R BT.656 8-bit */
|
||||
} else if (cam->bus_type == FIMC_MIPI_CSI2) {
|
||||
if (fimc_fmt_is_jpeg(f->fmt->color))
|
||||
if (fimc_fmt_is_user_defined(f->fmt->color))
|
||||
cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
|
||||
}
|
||||
|
||||
|
|
@ -680,6 +680,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
|
|||
tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
|
||||
break;
|
||||
case V4L2_MBUS_FMT_JPEG_1X8:
|
||||
case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
|
||||
tmp = FIMC_REG_CSIIMGFMT_USER(1);
|
||||
cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
|
||||
break;
|
||||
|
|
@ -744,13 +745,13 @@ void fimc_hw_dis_capture(struct fimc_dev *dev)
|
|||
}
|
||||
|
||||
/* Return an index to the buffer actually being written. */
|
||||
u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
|
||||
s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
|
||||
{
|
||||
u32 reg;
|
||||
s32 reg;
|
||||
|
||||
if (dev->variant->has_cistatus2) {
|
||||
reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F;
|
||||
return reg > 0 ? --reg : reg;
|
||||
reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
|
||||
return reg - 1;
|
||||
}
|
||||
|
||||
reg = readl(dev->regs + FIMC_REG_CISTATUS);
|
||||
|
|
@ -759,6 +760,18 @@ u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
|
|||
FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
|
||||
}
|
||||
|
||||
/* Return an index to the buffer being written previously. */
|
||||
s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
|
||||
{
|
||||
s32 reg;
|
||||
|
||||
if (!dev->variant->has_cistatus2)
|
||||
return -1;
|
||||
|
||||
reg = readl(dev->regs + FIMC_REG_CISTATUS2);
|
||||
return ((reg >> 7) & 0x3f) - 1;
|
||||
}
|
||||
|
||||
/* Locking: the caller holds fimc->slock */
|
||||
void fimc_activate_capture(struct fimc_ctx *ctx)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -307,7 +307,8 @@ void fimc_hw_clear_irq(struct fimc_dev *dev);
|
|||
void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
|
||||
void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
|
||||
void fimc_hw_dis_capture(struct fimc_dev *dev);
|
||||
u32 fimc_hw_get_frame_index(struct fimc_dev *dev);
|
||||
s32 fimc_hw_get_frame_index(struct fimc_dev *dev);
|
||||
s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev);
|
||||
void fimc_activate_capture(struct fimc_ctx *ctx);
|
||||
void fimc_deactivate_capture(struct fimc_dev *fimc);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
|
||||
*
|
||||
* Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
|
||||
* Sylwester Nawrocki, <s.nawrocki@samsung.com>
|
||||
* Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
@ -98,6 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
|
|||
#define CSIS_MAX_PIX_WIDTH 0xffff
|
||||
#define CSIS_MAX_PIX_HEIGHT 0xffff
|
||||
|
||||
/* Non-image packet data buffers */
|
||||
#define S5PCSIS_PKTDATA_ODD 0x2000
|
||||
#define S5PCSIS_PKTDATA_EVEN 0x3000
|
||||
#define S5PCSIS_PKTDATA_SIZE SZ_4K
|
||||
|
||||
enum {
|
||||
CSIS_CLK_MUX,
|
||||
CSIS_CLK_GATE,
|
||||
|
|
@ -110,8 +115,8 @@ static char *csi_clock_name[] = {
|
|||
#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
|
||||
|
||||
static const char * const csis_supply_name[] = {
|
||||
"vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
|
||||
"vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
|
||||
"vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
|
||||
"vddio", /* CSIS I/O and PLL (1.8V) supply */
|
||||
};
|
||||
#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
|
||||
|
||||
|
|
@ -144,12 +149,18 @@ static const struct s5pcsis_event s5pcsis_events[] = {
|
|||
};
|
||||
#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
|
||||
|
||||
struct csis_pktbuf {
|
||||
u32 *data;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct csis_state - the driver's internal state data structure
|
||||
* @lock: mutex serializing the subdev and power management operations,
|
||||
* protecting @format and @flags members
|
||||
* @pads: CSIS pads array
|
||||
* @sd: v4l2_subdev associated with CSIS device instance
|
||||
* @index: the hardware instance index
|
||||
* @pdev: CSIS platform device
|
||||
* @regs: mmaped I/O registers memory
|
||||
* @supplies: CSIS regulator supplies
|
||||
|
|
@ -159,12 +170,14 @@ static const struct s5pcsis_event s5pcsis_events[] = {
|
|||
* @csis_fmt: current CSIS pixel format
|
||||
* @format: common media bus format for the source and sink pad
|
||||
* @slock: spinlock protecting structure members below
|
||||
* @pkt_buf: the frame embedded (non-image) data buffer
|
||||
* @events: MIPI-CSIS event (error) counters
|
||||
*/
|
||||
struct csis_state {
|
||||
struct mutex lock;
|
||||
struct media_pad pads[CSIS_PADS_NUM];
|
||||
struct v4l2_subdev sd;
|
||||
u8 index;
|
||||
struct platform_device *pdev;
|
||||
void __iomem *regs;
|
||||
struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
|
||||
|
|
@ -175,6 +188,7 @@ struct csis_state {
|
|||
struct v4l2_mbus_framefmt format;
|
||||
|
||||
struct spinlock slock;
|
||||
struct csis_pktbuf pkt_buf;
|
||||
struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
|
||||
};
|
||||
|
||||
|
|
@ -202,7 +216,11 @@ static const struct csis_pix_format s5pcsis_formats[] = {
|
|||
.code = V4L2_MBUS_FMT_JPEG_1X8,
|
||||
.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
|
||||
.data_alignment = 32,
|
||||
},
|
||||
}, {
|
||||
.code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
|
||||
.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
|
||||
.data_alignment = 32,
|
||||
}
|
||||
};
|
||||
|
||||
#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
|
||||
|
|
@ -266,7 +284,7 @@ static void __s5pcsis_set_format(struct csis_state *state)
|
|||
struct v4l2_mbus_framefmt *mf = &state->format;
|
||||
u32 val;
|
||||
|
||||
v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
|
||||
v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
|
||||
mf->code, mf->width, mf->height);
|
||||
|
||||
/* Color format */
|
||||
|
|
@ -304,8 +322,10 @@ static void s5pcsis_set_params(struct csis_state *state)
|
|||
val |= S5PCSIS_CTRL_ALIGN_32BIT;
|
||||
else /* 24-bits */
|
||||
val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
|
||||
/* Not using external clock. */
|
||||
|
||||
val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
|
||||
if (pdata->wclk_source)
|
||||
val |= S5PCSIS_CTRL_WCLK_EXTCLK;
|
||||
s5pcsis_write(state, S5PCSIS_CTRL, val);
|
||||
|
||||
/* Update the shadow register. */
|
||||
|
|
@ -529,6 +549,22 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
|
||||
unsigned int *size)
|
||||
{
|
||||
struct csis_state *state = sd_to_csis_state(sd);
|
||||
unsigned long flags;
|
||||
|
||||
*size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
|
||||
|
||||
spin_lock_irqsave(&state->slock, flags);
|
||||
state->pkt_buf.data = buf;
|
||||
state->pkt_buf.len = *size;
|
||||
spin_unlock_irqrestore(&state->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5pcsis_log_status(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct csis_state *state = sd_to_csis_state(sd);
|
||||
|
|
@ -566,6 +602,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
|
|||
};
|
||||
|
||||
static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
|
||||
.s_rx_buffer = s5pcsis_s_rx_buffer,
|
||||
.s_stream = s5pcsis_s_stream,
|
||||
};
|
||||
|
||||
|
|
@ -578,13 +615,26 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
|
|||
static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct csis_state *state = dev_id;
|
||||
struct csis_pktbuf *pktbuf = &state->pkt_buf;
|
||||
unsigned long flags;
|
||||
u32 status;
|
||||
|
||||
status = s5pcsis_read(state, S5PCSIS_INTSRC);
|
||||
|
||||
spin_lock_irqsave(&state->slock, flags);
|
||||
|
||||
if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
|
||||
u32 offset;
|
||||
|
||||
if (status & S5PCSIS_INTSRC_EVEN)
|
||||
offset = S5PCSIS_PKTDATA_EVEN;
|
||||
else
|
||||
offset = S5PCSIS_PKTDATA_ODD;
|
||||
|
||||
memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
|
||||
pktbuf->data = NULL;
|
||||
rmb();
|
||||
}
|
||||
|
||||
/* Update the event/error counters */
|
||||
if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
|
||||
int i;
|
||||
|
|
@ -620,14 +670,15 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&state->slock);
|
||||
|
||||
state->pdev = pdev;
|
||||
state->index = max(0, pdev->id);
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (pdata == NULL || pdata->phy_enable == NULL) {
|
||||
if (pdata == NULL) {
|
||||
dev_err(&pdev->dev, "Platform data not fully specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
|
||||
if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
|
||||
pdata->lanes > CSIS0_MAX_LANES) {
|
||||
dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
|
||||
pdata->lanes);
|
||||
|
|
@ -710,7 +761,6 @@ e_clkput:
|
|||
|
||||
static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
|
||||
{
|
||||
struct s5p_platform_mipi_csis *pdata = dev->platform_data;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct v4l2_subdev *sd = platform_get_drvdata(pdev);
|
||||
struct csis_state *state = sd_to_csis_state(sd);
|
||||
|
|
@ -722,7 +772,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
|
|||
mutex_lock(&state->lock);
|
||||
if (state->flags & ST_POWERED) {
|
||||
s5pcsis_stop_stream(state);
|
||||
ret = pdata->phy_enable(state->pdev, false);
|
||||
ret = s5p_csis_phy_enable(state->index, false);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
|
||||
|
|
@ -741,7 +791,6 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
|
|||
|
||||
static int s5pcsis_pm_resume(struct device *dev, bool runtime)
|
||||
{
|
||||
struct s5p_platform_mipi_csis *pdata = dev->platform_data;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct v4l2_subdev *sd = platform_get_drvdata(pdev);
|
||||
struct csis_state *state = sd_to_csis_state(sd);
|
||||
|
|
@ -759,7 +808,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime)
|
|||
state->supplies);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
ret = pdata->phy_enable(state->pdev, true);
|
||||
ret = s5p_csis_phy_enable(state->index, true);
|
||||
if (!ret) {
|
||||
state->flags |= ST_POWERED;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
|
||||
static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
|
||||
{
|
||||
struct g2d_ctx *ctx = prv;
|
||||
struct g2d_dev *dev = ctx->dev;
|
||||
|
|
|
|||
|
|
@ -1353,7 +1353,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
|
||||
clk_enable(jpeg->clk);
|
||||
clk_prepare_enable(jpeg->clk);
|
||||
|
||||
/* v4l2 device */
|
||||
ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
|
||||
|
|
@ -1460,7 +1460,7 @@ device_register_rollback:
|
|||
v4l2_device_unregister(&jpeg->v4l2_dev);
|
||||
|
||||
clk_get_rollback:
|
||||
clk_disable(jpeg->clk);
|
||||
clk_disable_unprepare(jpeg->clk);
|
||||
clk_put(jpeg->clk);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1480,7 +1480,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
|
|||
v4l2_m2m_release(jpeg->m2m_dev);
|
||||
v4l2_device_unregister(&jpeg->v4l2_dev);
|
||||
|
||||
clk_disable(jpeg->clk);
|
||||
clk_disable_unprepare(jpeg->clk);
|
||||
clk_put(jpeg->clk);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
|
||||
s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
|
||||
s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
|
||||
s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
|
||||
s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
|
||||
s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
|
||||
s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
|
||||
s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
|
||||
s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
|
||||
|
|
|
|||
408
drivers/media/platform/s5p-mfc/regs-mfc-v6.h
Normal file
408
drivers/media/platform/s5p-mfc/regs-mfc-v6.h
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Register definition file for Samsung MFC V6.x Interface (FIMV) driver
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _REGS_FIMV_V6_H
|
||||
#define _REGS_FIMV_V6_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#define S5P_FIMV_REG_SIZE_V6 (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
|
||||
#define S5P_FIMV_REG_COUNT_V6 ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
|
||||
|
||||
/* Number of bits that the buffer address should be shifted for particular
|
||||
* MFC buffers. */
|
||||
#define S5P_FIMV_MEM_OFFSET_V6 0
|
||||
|
||||
#define S5P_FIMV_START_ADDR_V6 0x0000
|
||||
#define S5P_FIMV_END_ADDR_V6 0xfd80
|
||||
|
||||
#define S5P_FIMV_REG_CLEAR_BEGIN_V6 0xf000
|
||||
#define S5P_FIMV_REG_CLEAR_COUNT_V6 1024
|
||||
|
||||
/* Codec Common Registers */
|
||||
#define S5P_FIMV_RISC_ON_V6 0x0000
|
||||
#define S5P_FIMV_RISC2HOST_INT_V6 0x003C
|
||||
#define S5P_FIMV_HOST2RISC_INT_V6 0x0044
|
||||
#define S5P_FIMV_RISC_BASE_ADDRESS_V6 0x0054
|
||||
|
||||
#define S5P_FIMV_MFC_RESET_V6 0x1070
|
||||
|
||||
#define S5P_FIMV_HOST2RISC_CMD_V6 0x1100
|
||||
#define S5P_FIMV_H2R_CMD_EMPTY_V6 0
|
||||
#define S5P_FIMV_H2R_CMD_SYS_INIT_V6 1
|
||||
#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6 2
|
||||
#define S5P_FIMV_CH_SEQ_HEADER_V6 3
|
||||
#define S5P_FIMV_CH_INIT_BUFS_V6 4
|
||||
#define S5P_FIMV_CH_FRAME_START_V6 5
|
||||
#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6 6
|
||||
#define S5P_FIMV_H2R_CMD_SLEEP_V6 7
|
||||
#define S5P_FIMV_H2R_CMD_WAKEUP_V6 8
|
||||
#define S5P_FIMV_CH_LAST_FRAME_V6 9
|
||||
#define S5P_FIMV_H2R_CMD_FLUSH_V6 10
|
||||
/* RMVME: REALLOC used? */
|
||||
#define S5P_FIMV_CH_FRAME_START_REALLOC_V6 5
|
||||
|
||||
#define S5P_FIMV_RISC2HOST_CMD_V6 0x1104
|
||||
#define S5P_FIMV_R2H_CMD_EMPTY_V6 0
|
||||
#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6 1
|
||||
#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6 2
|
||||
#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6 3
|
||||
#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6 4
|
||||
|
||||
#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
|
||||
#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6 7
|
||||
#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6 8
|
||||
#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6 9
|
||||
#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6 10
|
||||
#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6 11
|
||||
#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6 12
|
||||
#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6 13
|
||||
#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6 14
|
||||
#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6 15
|
||||
#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
|
||||
#define S5P_FIMV_R2H_CMD_ERR_RET_V6 32
|
||||
|
||||
#define S5P_FIMV_FW_VERSION_V6 0xf000
|
||||
|
||||
#define S5P_FIMV_INSTANCE_ID_V6 0xf008
|
||||
#define S5P_FIMV_CODEC_TYPE_V6 0xf00c
|
||||
#define S5P_FIMV_CONTEXT_MEM_ADDR_V6 0xf014
|
||||
#define S5P_FIMV_CONTEXT_MEM_SIZE_V6 0xf018
|
||||
#define S5P_FIMV_PIXEL_FORMAT_V6 0xf020
|
||||
|
||||
#define S5P_FIMV_METADATA_ENABLE_V6 0xf024
|
||||
#define S5P_FIMV_DBG_BUFFER_ADDR_V6 0xf030
|
||||
#define S5P_FIMV_DBG_BUFFER_SIZE_V6 0xf034
|
||||
#define S5P_FIMV_RET_INSTANCE_ID_V6 0xf070
|
||||
|
||||
#define S5P_FIMV_ERROR_CODE_V6 0xf074
|
||||
#define S5P_FIMV_ERR_WARNINGS_START_V6 160
|
||||
#define S5P_FIMV_ERR_DEC_MASK_V6 0xffff
|
||||
#define S5P_FIMV_ERR_DEC_SHIFT_V6 0
|
||||
#define S5P_FIMV_ERR_DSPL_MASK_V6 0xffff0000
|
||||
#define S5P_FIMV_ERR_DSPL_SHIFT_V6 16
|
||||
|
||||
#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6 0xf078
|
||||
#define S5P_FIMV_METADATA_STATUS_V6 0xf07C
|
||||
#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6 0xf080
|
||||
#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6 0xf084
|
||||
|
||||
/* Decoder Registers */
|
||||
#define S5P_FIMV_D_CRC_CTRL_V6 0xf0b0
|
||||
#define S5P_FIMV_D_DEC_OPTIONS_V6 0xf0b4
|
||||
#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6 4
|
||||
#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6 3
|
||||
#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6 1
|
||||
#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6 0x3
|
||||
#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6 0
|
||||
|
||||
#define S5P_FIMV_D_DISPLAY_DELAY_V6 0xf0b8
|
||||
|
||||
#define S5P_FIMV_D_SET_FRAME_WIDTH_V6 0xf0bc
|
||||
#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6 0xf0c0
|
||||
|
||||
#define S5P_FIMV_D_SEI_ENABLE_V6 0xf0c4
|
||||
|
||||
/* Buffer setting registers */
|
||||
#define S5P_FIMV_D_MIN_NUM_DPB_V6 0xf0f0
|
||||
#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6 0xf0f4
|
||||
#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6 0xf0f8
|
||||
#define S5P_FIMV_D_MVC_NUM_VIEWS_V6 0xf0fc
|
||||
#define S5P_FIMV_D_MIN_NUM_MV_V6 0xf100
|
||||
#define S5P_FIMV_D_NUM_DPB_V6 0xf130
|
||||
#define S5P_FIMV_D_LUMA_DPB_SIZE_V6 0xf134
|
||||
#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6 0xf138
|
||||
#define S5P_FIMV_D_MV_BUFFER_SIZE_V6 0xf13c
|
||||
|
||||
#define S5P_FIMV_D_LUMA_DPB_V6 0xf140
|
||||
#define S5P_FIMV_D_CHROMA_DPB_V6 0xf240
|
||||
#define S5P_FIMV_D_MV_BUFFER_V6 0xf340
|
||||
|
||||
#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6 0xf440
|
||||
#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6 0xf444
|
||||
#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6 0xf448
|
||||
#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6 0xf44c
|
||||
#define S5P_FIMV_D_NUM_MV_V6 0xf478
|
||||
#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6 0xf4b0
|
||||
#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6 0xf4b4
|
||||
|
||||
#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
|
||||
#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
|
||||
#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6 0xf4c0
|
||||
#define S5P_FIMV_D_SLICE_IF_ENABLE_V6 0xf4c4
|
||||
#define S5P_FIMV_D_PICTURE_TAG_V6 0xf4c8
|
||||
#define S5P_FIMV_D_STREAM_DATA_SIZE_V6 0xf4d0
|
||||
|
||||
/* Display information register */
|
||||
#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6 0xf500
|
||||
#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6 0xf504
|
||||
|
||||
/* Display status */
|
||||
#define S5P_FIMV_D_DISPLAY_STATUS_V6 0xf508
|
||||
|
||||
#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6 0xf50c
|
||||
#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6 0xf510
|
||||
|
||||
#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6 0xf514
|
||||
|
||||
#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 0xf518
|
||||
#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 0xf51c
|
||||
#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6 0xf520
|
||||
#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6 0xf524
|
||||
#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6 0xf528
|
||||
#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6 0xf52c
|
||||
#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6 0xf530
|
||||
#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6 0xf534
|
||||
#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6 0xf538
|
||||
|
||||
/* Decoded picture information register */
|
||||
#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6 0xf53c
|
||||
#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6 0xf540
|
||||
#define S5P_FIMV_D_DECODED_STATUS_V6 0xf544
|
||||
#define S5P_FIMV_DEC_CRC_GEN_MASK_V6 0x1
|
||||
#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6 6
|
||||
|
||||
#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6 0xf548
|
||||
#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6 0xf54c
|
||||
|
||||
#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6 0xf550
|
||||
#define S5P_FIMV_DECODE_FRAME_MASK_V6 7
|
||||
|
||||
#define S5P_FIMV_D_DECODED_CROP_INFO1_V6 0xf554
|
||||
#define S5P_FIMV_D_DECODED_CROP_INFO2_V6 0xf558
|
||||
#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6 0xf55c
|
||||
#define S5P_FIMV_D_DECODED_NAL_SIZE_V6 0xf560
|
||||
#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6 0xf564
|
||||
#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6 0xf568
|
||||
#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6 0xf56c
|
||||
#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6 0xf570
|
||||
|
||||
/* Returned value register for specific setting */
|
||||
#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 0xf574
|
||||
#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 0xf578
|
||||
#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6 0xf57c
|
||||
#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6 0xf580
|
||||
#define S5P_FIMV_D_CHROMA_FORMAT_V6 0xf588
|
||||
#define S5P_FIMV_D_MPEG4_INFO_V6 0xf58c
|
||||
#define S5P_FIMV_D_H264_INFO_V6 0xf590
|
||||
|
||||
#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6 0xf594
|
||||
#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6 0xf598
|
||||
#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6 0xf59c
|
||||
#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6 0xf5a0
|
||||
#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6 0xf5a4
|
||||
#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6 0xf5a8
|
||||
#define S5P_FIMV_D_METADATA_ADDR_VUI_V6 0xf5ac
|
||||
#define S5P_FIMV_D_METADATA_SIZE_VUI_V6 0xf5b0
|
||||
|
||||
#define S5P_FIMV_D_MVC_VIEW_ID_V6 0xf5b4
|
||||
|
||||
/* SEI related information */
|
||||
#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6 0xf5f0
|
||||
#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6 0xf5f4
|
||||
#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6 0xf5f8
|
||||
#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6 0xf5fc
|
||||
|
||||
/* Encoder Registers */
|
||||
#define S5P_FIMV_E_FRAME_WIDTH_V6 0xf770
|
||||
#define S5P_FIMV_E_FRAME_HEIGHT_V6 0xf774
|
||||
#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6 0xf778
|
||||
#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6 0xf77c
|
||||
#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6 0xf780
|
||||
#define S5P_FIMV_E_ENC_OPTIONS_V6 0xf784
|
||||
#define S5P_FIMV_E_PICTURE_PROFILE_V6 0xf788
|
||||
#define S5P_FIMV_E_FIXED_PICTURE_QP_V6 0xf790
|
||||
|
||||
#define S5P_FIMV_E_RC_CONFIG_V6 0xf794
|
||||
#define S5P_FIMV_E_RC_QP_BOUND_V6 0xf798
|
||||
#define S5P_FIMV_E_RC_RPARAM_V6 0xf79c
|
||||
#define S5P_FIMV_E_MB_RC_CONFIG_V6 0xf7a0
|
||||
#define S5P_FIMV_E_PADDING_CTRL_V6 0xf7a4
|
||||
#define S5P_FIMV_E_MV_HOR_RANGE_V6 0xf7ac
|
||||
#define S5P_FIMV_E_MV_VER_RANGE_V6 0xf7b0
|
||||
|
||||
#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6 0xf84c
|
||||
#define S5P_FIMV_E_VBV_INIT_DELAY_V6 0xf850
|
||||
#define S5P_FIMV_E_NUM_DPB_V6 0xf890
|
||||
#define S5P_FIMV_E_LUMA_DPB_V6 0xf8c0
|
||||
#define S5P_FIMV_E_CHROMA_DPB_V6 0xf904
|
||||
#define S5P_FIMV_E_ME_BUFFER_V6 0xf948
|
||||
|
||||
#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6 0xf98c
|
||||
#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6 0xf990
|
||||
#define S5P_FIMV_E_TMV_BUFFER0_V6 0xf994
|
||||
#define S5P_FIMV_E_TMV_BUFFER1_V6 0xf998
|
||||
#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6 0xf9f0
|
||||
#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6 0xf9f4
|
||||
#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6 0xf9f8
|
||||
#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6 0xf9fc
|
||||
#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6 0xfA00
|
||||
|
||||
#define S5P_FIMV_E_PARAM_CHANGE_V6 0xfa04
|
||||
#define S5P_FIMV_E_IR_SIZE_V6 0xfa08
|
||||
#define S5P_FIMV_E_GOP_CONFIG_V6 0xfa0c
|
||||
#define S5P_FIMV_E_MSLICE_MODE_V6 0xfa10
|
||||
#define S5P_FIMV_E_MSLICE_SIZE_MB_V6 0xfa14
|
||||
#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6 0xfa18
|
||||
#define S5P_FIMV_E_FRAME_INSERTION_V6 0xfa1c
|
||||
|
||||
#define S5P_FIMV_E_RC_FRAME_RATE_V6 0xfa20
|
||||
#define S5P_FIMV_E_RC_BIT_RATE_V6 0xfa24
|
||||
#define S5P_FIMV_E_RC_QP_OFFSET_V6 0xfa28
|
||||
#define S5P_FIMV_E_RC_ROI_CTRL_V6 0xfa2c
|
||||
#define S5P_FIMV_E_PICTURE_TAG_V6 0xfa30
|
||||
#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6 0xfa34
|
||||
#define S5P_FIMV_E_MAX_BIT_COUNT_V6 0xfa38
|
||||
#define S5P_FIMV_E_MIN_BIT_COUNT_V6 0xfa3c
|
||||
|
||||
#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6 0xfa40
|
||||
#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6 0xfa44
|
||||
#define S5P_FIMV_E_STREAM_SIZE_V6 0xfa80
|
||||
#define S5P_FIMV_E_SLICE_TYPE_V6 0xfa84
|
||||
#define S5P_FIMV_E_PICTURE_COUNT_V6 0xfa88
|
||||
#define S5P_FIMV_E_RET_PICTURE_TAG_V6 0xfa8c
|
||||
#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6 0xfa90
|
||||
|
||||
#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6 0xfa94
|
||||
#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6 0xfa98
|
||||
#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6 0xfa9c
|
||||
#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6 0xfaa0
|
||||
#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6 0xfaa4
|
||||
#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6 0xfaa8
|
||||
|
||||
#define S5P_FIMV_E_MPEG4_OPTIONS_V6 0xfb10
|
||||
#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6 0xfb14
|
||||
#define S5P_FIMV_E_ASPECT_RATIO_V6 0xfb50
|
||||
#define S5P_FIMV_E_EXTENDED_SAR_V6 0xfb54
|
||||
|
||||
#define S5P_FIMV_E_H264_OPTIONS_V6 0xfb58
|
||||
#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6 0xfb5c
|
||||
#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6 0xfb60
|
||||
#define S5P_FIMV_E_H264_I_PERIOD_V6 0xfb64
|
||||
|
||||
#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6 0xfb68
|
||||
#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6 0xfb6c
|
||||
#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6 0xfb70
|
||||
#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6 0xfb74
|
||||
#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 0xfb78
|
||||
#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6 0xfb7c
|
||||
#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6 0xfb80
|
||||
#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6 0xfb84
|
||||
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 0xfb88
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6 0xfb8c
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6 0xfb90
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6 0xfb94
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6 0xfb98
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6 0xfb9c
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6 0xfba0
|
||||
#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6 0xfba4
|
||||
|
||||
#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6 0xfba8
|
||||
#define S5P_FIMV_E_H264_NUM_T_LAYER_V6 0xfbac
|
||||
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 0xfbb0
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6 0xfbb4
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6 0xfbb8
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6 0xfbbc
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6 0xfbc0
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6 0xfbc4
|
||||
#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6 0xfbc8
|
||||
|
||||
#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6 0xfc4c
|
||||
#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6 0
|
||||
#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6 1
|
||||
#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6 2
|
||||
|
||||
#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6 0xfd40
|
||||
#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6 0xfd44
|
||||
#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6 0xfd48
|
||||
#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6 0xfd4c
|
||||
#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6 0xfd50
|
||||
#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6 0xfd80
|
||||
|
||||
/* Codec numbers */
|
||||
#define S5P_FIMV_CODEC_NONE_V6 -1
|
||||
|
||||
|
||||
#define S5P_FIMV_CODEC_H264_DEC_V6 0
|
||||
#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
|
||||
|
||||
#define S5P_FIMV_CODEC_MPEG4_DEC_V6 3
|
||||
#define S5P_FIMV_CODEC_FIMV1_DEC_V6 4
|
||||
#define S5P_FIMV_CODEC_FIMV2_DEC_V6 5
|
||||
#define S5P_FIMV_CODEC_FIMV3_DEC_V6 6
|
||||
#define S5P_FIMV_CODEC_FIMV4_DEC_V6 7
|
||||
#define S5P_FIMV_CODEC_H263_DEC_V6 8
|
||||
#define S5P_FIMV_CODEC_VC1RCV_DEC_V6 9
|
||||
#define S5P_FIMV_CODEC_VC1_DEC_V6 10
|
||||
/* FIXME: Add 11~12 */
|
||||
#define S5P_FIMV_CODEC_MPEG2_DEC_V6 13
|
||||
#define S5P_FIMV_CODEC_VP8_DEC_V6 14
|
||||
/* FIXME: Add 15~16 */
|
||||
#define S5P_FIMV_CODEC_H264_ENC_V6 20
|
||||
#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
|
||||
|
||||
#define S5P_FIMV_CODEC_MPEG4_ENC_V6 23
|
||||
#define S5P_FIMV_CODEC_H263_ENC_V6 24
|
||||
|
||||
#define S5P_FIMV_NV12M_HALIGN_V6 16
|
||||
#define S5P_FIMV_NV12MT_HALIGN_V6 16
|
||||
#define S5P_FIMV_NV12MT_VALIGN_V6 16
|
||||
|
||||
#define S5P_FIMV_TMV_BUFFER_ALIGN_V6 16
|
||||
#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6 256
|
||||
#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6 256
|
||||
#define S5P_FIMV_ME_BUFFER_ALIGN_V6 256
|
||||
#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6 256
|
||||
|
||||
#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6 256
|
||||
#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6 128
|
||||
#define S5P_FIMV_NUM_TMV_BUFFERS_V6 2
|
||||
|
||||
#define S5P_FIMV_MAX_FRAME_SIZE_V6 (2 * SZ_1M)
|
||||
#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6 16
|
||||
#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16
|
||||
|
||||
/* Buffer size requirements defined by hardware */
|
||||
#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8)
|
||||
#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
|
||||
((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \
|
||||
(DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64)
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
|
||||
((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \
|
||||
(2048/16 * 256 + 8320))
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
|
||||
(2096 * ((w) + (h) + 1))
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h) ((w) * 400)
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
|
||||
((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
|
||||
(((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
|
||||
(((w) * 16) + (((w) + 1) * 16))
|
||||
|
||||
/* MFC Context buffer sizes */
|
||||
#define MFC_CTX_BUF_SIZE_V6 (28 * SZ_1K) /* 28KB */
|
||||
#define MFC_H264_DEC_CTX_BUF_SIZE_V6 (2 * SZ_1M) /* 2MB */
|
||||
#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6 (20 * SZ_1K) /* 20KB */
|
||||
#define MFC_H264_ENC_CTX_BUF_SIZE_V6 (100 * SZ_1K) /* 100KB */
|
||||
#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6 (12 * SZ_1K) /* 12KB */
|
||||
|
||||
/* MFCv6 variant defines */
|
||||
#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */
|
||||
#define MAX_CPB_SIZE_V6 (3 * SZ_1M) /* 3MB */
|
||||
#define MFC_VERSION_V6 0x61
|
||||
#define MFC_NUM_PORTS_V6 1
|
||||
|
||||
#endif /* _REGS_FIMV_V6_H */
|
||||
|
|
@ -12,6 +12,9 @@
|
|||
#ifndef _REGS_FIMV_H
|
||||
#define _REGS_FIMV_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
|
||||
#define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
|
||||
|
||||
|
|
@ -144,6 +147,7 @@
|
|||
#define S5P_FIMV_ENC_PROFILE_H264_MAIN 0
|
||||
#define S5P_FIMV_ENC_PROFILE_H264_HIGH 1
|
||||
#define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2
|
||||
#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
|
||||
#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0
|
||||
#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1
|
||||
#define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */
|
||||
|
|
@ -213,6 +217,7 @@
|
|||
#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4)
|
||||
#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4)
|
||||
#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4)
|
||||
#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT 4
|
||||
|
||||
/* Decode frame address */
|
||||
#define S5P_FIMV_DECODE_Y_ADR 0x2024
|
||||
|
|
@ -377,6 +382,16 @@
|
|||
#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16
|
||||
#define S5P_FIMV_R2H_CMD_ERR_RET 32
|
||||
|
||||
/* Dummy definition for MFCv6 compatibilty */
|
||||
#define S5P_FIMV_CODEC_H264_MVC_DEC -1
|
||||
#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1
|
||||
#define S5P_FIMV_MFC_RESET -1
|
||||
#define S5P_FIMV_RISC_ON -1
|
||||
#define S5P_FIMV_RISC_BASE_ADDRESS -1
|
||||
#define S5P_FIMV_CODEC_VP8_DEC -1
|
||||
#define S5P_FIMV_REG_CLEAR_BEGIN 0
|
||||
#define S5P_FIMV_REG_CLEAR_COUNT 0
|
||||
|
||||
/* Error handling defines */
|
||||
#define S5P_FIMV_ERR_WARNINGS_START 145
|
||||
#define S5P_FIMV_ERR_DEC_MASK 0xFFFF
|
||||
|
|
@ -414,5 +429,31 @@
|
|||
#define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078
|
||||
#define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C
|
||||
#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0
|
||||
#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT 2
|
||||
|
||||
/* Offset used by the hardware to store addresses */
|
||||
#define MFC_OFFSET_SHIFT 11
|
||||
|
||||
#define FIRMWARE_ALIGN (128 * SZ_1K) /* 128KB */
|
||||
#define MFC_H264_CTX_BUF_SIZE (600 * SZ_1K) /* 600KB per H264 instance */
|
||||
#define MFC_CTX_BUF_SIZE (10 * SZ_1K) /* 10KB per instance */
|
||||
#define DESC_BUF_SIZE (128 * SZ_1K) /* 128KB for DESC buffer */
|
||||
#define SHARED_BUF_SIZE (8 * SZ_1K) /* 8KB for shared buffer */
|
||||
|
||||
#define DEF_CPB_SIZE (256 * SZ_1K) /* 256KB */
|
||||
#define MAX_CPB_SIZE (4 * SZ_1M) /* 4MB */
|
||||
#define MAX_FW_SIZE (384 * SZ_1K)
|
||||
|
||||
#define MFC_VERSION 0x51
|
||||
#define MFC_NUM_PORTS 2
|
||||
|
||||
#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL 0x16C
|
||||
#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID 0x170
|
||||
#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO 0x174
|
||||
#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS 0x178
|
||||
|
||||
/* Values for resolution change in display status */
|
||||
#define S5P_FIMV_RES_INCREASE 1
|
||||
#define S5P_FIMV_RES_DECREASE 2
|
||||
|
||||
#endif /* _REGS_FIMV_H */
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@
|
|||
#include <media/v4l2-event.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_ctrl.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_dec.h"
|
||||
#include "s5p_mfc_enc.h"
|
||||
#include "s5p_mfc_intr.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
#include "s5p_mfc_cmd.h"
|
||||
#include "s5p_mfc_pm.h"
|
||||
#include "s5p_mfc_shm.h"
|
||||
|
||||
#define S5P_MFC_NAME "s5p-mfc"
|
||||
#define S5P_MFC_DEC_NAME "s5p-mfc-dec"
|
||||
|
|
@ -149,10 +149,12 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work)
|
|||
if (!ctx)
|
||||
continue;
|
||||
ctx->state = MFCINST_ERROR;
|
||||
s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
|
||||
s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
|
||||
&ctx->vq_dst);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
|
||||
&ctx->vq_src);
|
||||
clear_work_bit(ctx);
|
||||
wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
|
||||
wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
|
||||
}
|
||||
clear_bit(0, &dev->hw_lock);
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
|
|
@ -199,6 +201,7 @@ static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
|
|||
static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_buf *dst_buf;
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
|
||||
ctx->state = MFCINST_FINISHED;
|
||||
ctx->sequence++;
|
||||
|
|
@ -213,8 +216,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
|
|||
ctx->dst_queue_cnt--;
|
||||
dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
|
||||
|
||||
if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
|
||||
s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
|
||||
if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
|
||||
s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
|
||||
dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
|
||||
else
|
||||
dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
|
||||
|
|
@ -228,8 +231,11 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
|
|||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_buf *dst_buf, *src_buf;
|
||||
size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
|
||||
unsigned int frame_type = s5p_mfc_get_frame_type();
|
||||
size_t dec_y_addr;
|
||||
unsigned int frame_type;
|
||||
|
||||
dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
|
||||
frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
|
||||
|
||||
/* Copy timestamp / timecode from decoded src to dst and set
|
||||
appropraite flags */
|
||||
|
|
@ -265,10 +271,13 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
|
|||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_buf *dst_buf;
|
||||
size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
|
||||
unsigned int frame_type = s5p_mfc_get_frame_type();
|
||||
size_t dspl_y_addr;
|
||||
unsigned int frame_type;
|
||||
unsigned int index;
|
||||
|
||||
dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
|
||||
frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
|
||||
|
||||
/* If frame is same as previous then skip and do not dequeue */
|
||||
if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
|
||||
if (!ctx->after_packed_pb)
|
||||
|
|
@ -285,8 +294,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
|
|||
list_del(&dst_buf->list);
|
||||
ctx->dst_queue_cnt--;
|
||||
dst_buf->b->v4l2_buf.sequence = ctx->sequence;
|
||||
if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
|
||||
s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
|
||||
if (s5p_mfc_hw_call(dev->mfc_ops,
|
||||
get_pic_type_top, ctx) ==
|
||||
s5p_mfc_hw_call(dev->mfc_ops,
|
||||
get_pic_type_bot, ctx))
|
||||
dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
|
||||
else
|
||||
dst_buf->b->v4l2_buf.field =
|
||||
|
|
@ -317,21 +328,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
|
|||
|
||||
unsigned int index;
|
||||
|
||||
dst_frame_status = s5p_mfc_get_dspl_status()
|
||||
dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
|
||||
& S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
|
||||
res_change = s5p_mfc_get_dspl_status()
|
||||
& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
|
||||
res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
|
||||
& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
|
||||
>> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
|
||||
mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
|
||||
if (ctx->state == MFCINST_RES_CHANGE_INIT)
|
||||
ctx->state = MFCINST_RES_CHANGE_FLUSH;
|
||||
if (res_change) {
|
||||
if (res_change == S5P_FIMV_RES_INCREASE ||
|
||||
res_change == S5P_FIMV_RES_DECREASE) {
|
||||
ctx->state = MFCINST_RES_CHANGE_INIT;
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
wake_up_ctx(ctx, reason, err);
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
s5p_mfc_clock_off();
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
return;
|
||||
}
|
||||
if (ctx->dpb_flush_flag)
|
||||
|
|
@ -365,9 +378,12 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
|
|||
&& !list_empty(&ctx->src_queue)) {
|
||||
src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
|
||||
list);
|
||||
ctx->consumed_stream += s5p_mfc_get_consumed_stream();
|
||||
if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
|
||||
s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
|
||||
ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
|
||||
get_consumed_stream, dev);
|
||||
if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
|
||||
s5p_mfc_hw_call(dev->mfc_ops,
|
||||
get_dec_frame_type, dev) ==
|
||||
S5P_FIMV_DECODE_FRAME_P_FRAME
|
||||
&& ctx->consumed_stream + STUFF_BYTE <
|
||||
src_buf->b->v4l2_planes[0].bytesused) {
|
||||
/* Run MFC again on the same buffer */
|
||||
|
|
@ -379,7 +395,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
|
|||
ctx->consumed_stream = 0;
|
||||
list_del(&src_buf->list);
|
||||
ctx->src_queue_cnt--;
|
||||
if (s5p_mfc_err_dec(err) > 0)
|
||||
if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
|
||||
vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR);
|
||||
else
|
||||
vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE);
|
||||
|
|
@ -390,12 +406,12 @@ leave_handle_frame:
|
|||
if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
|
||||
|| ctx->dst_queue_cnt < ctx->dpb_count)
|
||||
clear_work_bit(ctx);
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
wake_up_ctx(ctx, reason, err);
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
s5p_mfc_clock_off();
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
}
|
||||
|
||||
/* Error handling for interrupt */
|
||||
|
|
@ -412,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
|
|||
|
||||
dev = ctx->dev;
|
||||
mfc_err("Interrupt Error: %08x\n", err);
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
wake_up_dev(dev, reason, err);
|
||||
|
||||
/* Error recovery is dependent on the state of context */
|
||||
|
|
@ -441,9 +457,11 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
|
|||
ctx->state = MFCINST_ERROR;
|
||||
/* Mark all dst buffers as having an error */
|
||||
spin_lock_irqsave(&dev->irqlock, flags);
|
||||
s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
|
||||
&ctx->vq_dst);
|
||||
/* Mark all src buffers as having an error */
|
||||
s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
|
||||
&ctx->vq_src);
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
|
|
@ -461,7 +479,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
|
|||
unsigned int reason, unsigned int err)
|
||||
{
|
||||
struct s5p_mfc_dev *dev;
|
||||
unsigned int guard_width, guard_height;
|
||||
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
|
@ -470,55 +487,44 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
|
|||
if (ctx->c_ops->post_seq_start(ctx))
|
||||
mfc_err("post_seq_start() failed\n");
|
||||
} else {
|
||||
ctx->img_width = s5p_mfc_get_img_width();
|
||||
ctx->img_height = s5p_mfc_get_img_height();
|
||||
ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
|
||||
dev);
|
||||
ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
|
||||
dev);
|
||||
|
||||
ctx->buf_width = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12MT_HALIGN);
|
||||
ctx->buf_height = ALIGN(ctx->img_height,
|
||||
S5P_FIMV_NV12MT_VALIGN);
|
||||
mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
|
||||
"buffer dimensions: %dx%d\n", ctx->img_width,
|
||||
ctx->img_height, ctx->buf_width,
|
||||
ctx->buf_height);
|
||||
if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
|
||||
ctx->luma_size = ALIGN(ctx->buf_width *
|
||||
ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
|
||||
ctx->chroma_size = ALIGN(ctx->buf_width *
|
||||
ALIGN((ctx->img_height >> 1),
|
||||
S5P_FIMV_NV12MT_VALIGN),
|
||||
S5P_FIMV_DEC_BUF_ALIGN);
|
||||
ctx->mv_size = ALIGN(ctx->buf_width *
|
||||
ALIGN((ctx->buf_height >> 2),
|
||||
S5P_FIMV_NV12MT_VALIGN),
|
||||
S5P_FIMV_DEC_BUF_ALIGN);
|
||||
} else {
|
||||
guard_width = ALIGN(ctx->img_width + 24,
|
||||
S5P_FIMV_NV12MT_HALIGN);
|
||||
guard_height = ALIGN(ctx->img_height + 16,
|
||||
S5P_FIMV_NV12MT_VALIGN);
|
||||
ctx->luma_size = ALIGN(guard_width *
|
||||
guard_height, S5P_FIMV_DEC_BUF_ALIGN);
|
||||
guard_width = ALIGN(ctx->img_width + 16,
|
||||
S5P_FIMV_NV12MT_HALIGN);
|
||||
guard_height = ALIGN((ctx->img_height >> 1) + 4,
|
||||
S5P_FIMV_NV12MT_VALIGN);
|
||||
ctx->chroma_size = ALIGN(guard_width *
|
||||
guard_height, S5P_FIMV_DEC_BUF_ALIGN);
|
||||
ctx->mv_size = 0;
|
||||
}
|
||||
ctx->dpb_count = s5p_mfc_get_dpb_count();
|
||||
s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
|
||||
|
||||
ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
|
||||
dev);
|
||||
ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
|
||||
dev);
|
||||
if (ctx->img_width == 0 || ctx->img_height == 0)
|
||||
ctx->state = MFCINST_ERROR;
|
||||
else
|
||||
ctx->state = MFCINST_HEAD_PARSED;
|
||||
|
||||
if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
|
||||
ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
|
||||
!list_empty(&ctx->src_queue)) {
|
||||
struct s5p_mfc_buf *src_buf;
|
||||
src_buf = list_entry(ctx->src_queue.next,
|
||||
struct s5p_mfc_buf, list);
|
||||
if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
|
||||
dev) <
|
||||
src_buf->b->v4l2_planes[0].bytesused)
|
||||
ctx->head_processed = 0;
|
||||
else
|
||||
ctx->head_processed = 1;
|
||||
} else {
|
||||
ctx->head_processed = 1;
|
||||
}
|
||||
}
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
clear_work_bit(ctx);
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
s5p_mfc_clock_off();
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
wake_up_ctx(ctx, reason, err);
|
||||
}
|
||||
|
||||
|
|
@ -533,14 +539,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
|
|||
if (ctx == NULL)
|
||||
return;
|
||||
dev = ctx->dev;
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
ctx->int_type = reason;
|
||||
ctx->int_err = err;
|
||||
ctx->int_cond = 1;
|
||||
clear_work_bit(ctx);
|
||||
if (err == 0) {
|
||||
ctx->state = MFCINST_RUNNING;
|
||||
if (!ctx->dpb_flush_flag) {
|
||||
if (!ctx->dpb_flush_flag && ctx->head_processed) {
|
||||
spin_lock_irqsave(&dev->irqlock, flags);
|
||||
if (!list_empty(&ctx->src_queue)) {
|
||||
src_buf = list_entry(ctx->src_queue.next,
|
||||
|
|
@ -560,7 +566,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
|
|||
s5p_mfc_clock_off();
|
||||
|
||||
wake_up(&ctx->queue);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
} else {
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
|
|
@ -602,7 +608,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
|
|||
|
||||
s5p_mfc_clock_off();
|
||||
wake_up(&ctx->queue);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
}
|
||||
|
||||
/* Interrupt processing */
|
||||
|
|
@ -618,81 +624,83 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
|
|||
atomic_set(&dev->watchdog_cnt, 0);
|
||||
ctx = dev->ctx[dev->curr_ctx];
|
||||
/* Get the reason of interrupt and the error code */
|
||||
reason = s5p_mfc_get_int_reason();
|
||||
err = s5p_mfc_get_int_err();
|
||||
reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
|
||||
err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
|
||||
mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
|
||||
switch (reason) {
|
||||
case S5P_FIMV_R2H_CMD_ERR_RET:
|
||||
case S5P_MFC_R2H_CMD_ERR_RET:
|
||||
/* An error has occured */
|
||||
if (ctx->state == MFCINST_RUNNING &&
|
||||
s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START)
|
||||
s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
|
||||
dev->warn_start)
|
||||
s5p_mfc_handle_frame(ctx, reason, err);
|
||||
else
|
||||
s5p_mfc_handle_error(ctx, reason, err);
|
||||
clear_bit(0, &dev->enter_suspend);
|
||||
break;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
|
||||
case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
|
||||
case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
|
||||
case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
|
||||
case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
|
||||
if (ctx->c_ops->post_frame_start) {
|
||||
if (ctx->c_ops->post_frame_start(ctx))
|
||||
mfc_err("post_frame_start() failed\n");
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
wake_up_ctx(ctx, reason, err);
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
s5p_mfc_clock_off();
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
} else {
|
||||
s5p_mfc_handle_frame(ctx, reason, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
|
||||
case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
|
||||
s5p_mfc_handle_seq_done(ctx, reason, err);
|
||||
break;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
|
||||
ctx->inst_no = s5p_mfc_get_inst_no();
|
||||
case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
|
||||
ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
|
||||
ctx->state = MFCINST_GOT_INST;
|
||||
clear_work_bit(ctx);
|
||||
wake_up(&ctx->queue);
|
||||
goto irq_cleanup_hw;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
|
||||
case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
|
||||
clear_work_bit(ctx);
|
||||
ctx->state = MFCINST_FREE;
|
||||
wake_up(&ctx->queue);
|
||||
goto irq_cleanup_hw;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
|
||||
case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
|
||||
case S5P_FIMV_R2H_CMD_SLEEP_RET:
|
||||
case S5P_FIMV_R2H_CMD_WAKEUP_RET:
|
||||
case S5P_MFC_R2H_CMD_SYS_INIT_RET:
|
||||
case S5P_MFC_R2H_CMD_FW_STATUS_RET:
|
||||
case S5P_MFC_R2H_CMD_SLEEP_RET:
|
||||
case S5P_MFC_R2H_CMD_WAKEUP_RET:
|
||||
if (ctx)
|
||||
clear_work_bit(ctx);
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
wake_up_dev(dev, reason, err);
|
||||
clear_bit(0, &dev->hw_lock);
|
||||
clear_bit(0, &dev->enter_suspend);
|
||||
break;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
|
||||
case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
|
||||
s5p_mfc_handle_init_buffers(ctx, reason, err);
|
||||
break;
|
||||
|
||||
case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
|
||||
case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
|
||||
s5p_mfc_handle_stream_complete(ctx, reason, err);
|
||||
break;
|
||||
|
||||
default:
|
||||
mfc_debug(2, "Unknown int reason\n");
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
}
|
||||
mfc_debug_leave();
|
||||
return IRQ_HANDLED;
|
||||
irq_cleanup_hw:
|
||||
s5p_mfc_clear_int_flags(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
|
||||
ctx->int_type = reason;
|
||||
ctx->int_err = err;
|
||||
ctx->int_cond = 1;
|
||||
|
|
@ -701,7 +709,7 @@ irq_cleanup_hw:
|
|||
|
||||
s5p_mfc_clock_off();
|
||||
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
mfc_debug(2, "Exit via irq_cleanup_hw\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
@ -749,6 +757,7 @@ static int s5p_mfc_open(struct file *file)
|
|||
if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
|
||||
ctx->type = MFCINST_DECODER;
|
||||
ctx->c_ops = get_dec_codec_ops();
|
||||
s5p_mfc_dec_init(ctx);
|
||||
/* Setup ctrl handler */
|
||||
ret = s5p_mfc_dec_ctrls_setup(ctx);
|
||||
if (ret) {
|
||||
|
|
@ -761,6 +770,7 @@ static int s5p_mfc_open(struct file *file)
|
|||
/* only for encoder */
|
||||
INIT_LIST_HEAD(&ctx->ref_queue);
|
||||
ctx->ref_queue_cnt = 0;
|
||||
s5p_mfc_enc_init(ctx);
|
||||
/* Setup ctrl handler */
|
||||
ret = s5p_mfc_enc_ctrls_setup(ctx);
|
||||
if (ret) {
|
||||
|
|
@ -886,19 +896,20 @@ static int s5p_mfc_release(struct file *file)
|
|||
ctx->state = MFCINST_RETURN_INST;
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_clean_ctx_int_flags(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
/* Wait until instance is returned or timeout occured */
|
||||
if (s5p_mfc_wait_for_done_ctx
|
||||
(ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
|
||||
(ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
|
||||
s5p_mfc_clock_off();
|
||||
mfc_err("Err returning instance\n");
|
||||
}
|
||||
mfc_debug(2, "After free instance\n");
|
||||
/* Free resources */
|
||||
s5p_mfc_release_codec_buffers(ctx);
|
||||
s5p_mfc_release_instance_buffer(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
|
||||
if (ctx->type == MFCINST_DECODER)
|
||||
s5p_mfc_release_dec_desc_buffer(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer,
|
||||
ctx);
|
||||
|
||||
ctx->inst_no = MFC_NO_INSTANCE_SET;
|
||||
}
|
||||
|
|
@ -910,6 +921,7 @@ static int s5p_mfc_release(struct file *file)
|
|||
mfc_debug(2, "Last instance - release firmware\n");
|
||||
/* reset <-> F/W release */
|
||||
s5p_mfc_reset(dev);
|
||||
s5p_mfc_deinit_hw(dev);
|
||||
s5p_mfc_release_firmware(dev);
|
||||
del_timer_sync(&dev->watchdog_timer);
|
||||
if (s5p_mfc_power_off() < 0)
|
||||
|
|
@ -1041,6 +1053,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev->variant = (struct s5p_mfc_variant *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
ret = s5p_mfc_init_pm(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get mfc clock source\n");
|
||||
|
|
@ -1076,6 +1091,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
|
|||
ret = -ENODEV;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
|
||||
match_child);
|
||||
if (!dev->mem_dev_r) {
|
||||
|
|
@ -1139,6 +1155,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
|
|||
vfd->release = video_device_release,
|
||||
vfd->lock = &dev->mfc_mutex;
|
||||
vfd->v4l2_dev = &dev->v4l2_dev;
|
||||
vfd->vfl_dir = VFL_DIR_M2M;
|
||||
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
|
||||
dev->vfd_enc = vfd;
|
||||
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
|
||||
|
|
@ -1160,6 +1177,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
|
|||
dev->watchdog_timer.data = (unsigned long)dev;
|
||||
dev->watchdog_timer.function = s5p_mfc_watchdog;
|
||||
|
||||
/* Initialize HW ops and commands based on MFC version */
|
||||
s5p_mfc_init_hw_ops(dev);
|
||||
s5p_mfc_init_hw_cmds(dev);
|
||||
|
||||
pr_debug("%s--\n", __func__);
|
||||
return 0;
|
||||
|
||||
|
|
@ -1280,9 +1301,78 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
|
|||
NULL)
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
|
||||
.h264_ctx = MFC_H264_CTX_BUF_SIZE,
|
||||
.non_h264_ctx = MFC_CTX_BUF_SIZE,
|
||||
.dsc = DESC_BUF_SIZE,
|
||||
.shm = SHARED_BUF_SIZE,
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size buf_size_v5 = {
|
||||
.fw = MAX_FW_SIZE,
|
||||
.cpb = MAX_CPB_SIZE,
|
||||
.priv = &mfc_buf_size_v5,
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_align mfc_buf_align_v5 = {
|
||||
.base = MFC_BASE_ALIGN_ORDER,
|
||||
};
|
||||
|
||||
static struct s5p_mfc_variant mfc_drvdata_v5 = {
|
||||
.version = MFC_VERSION,
|
||||
.port_num = MFC_NUM_PORTS,
|
||||
.buf_size = &buf_size_v5,
|
||||
.buf_align = &mfc_buf_align_v5,
|
||||
.mclk_name = "sclk_mfc",
|
||||
.fw_name = "s5p-mfc.fw",
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
|
||||
.dev_ctx = MFC_CTX_BUF_SIZE_V6,
|
||||
.h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V6,
|
||||
.other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
|
||||
.h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V6,
|
||||
.other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size buf_size_v6 = {
|
||||
.fw = MAX_FW_SIZE_V6,
|
||||
.cpb = MAX_CPB_SIZE_V6,
|
||||
.priv = &mfc_buf_size_v6,
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_align mfc_buf_align_v6 = {
|
||||
.base = 0,
|
||||
};
|
||||
|
||||
static struct s5p_mfc_variant mfc_drvdata_v6 = {
|
||||
.version = MFC_VERSION_V6,
|
||||
.port_num = MFC_NUM_PORTS_V6,
|
||||
.buf_size = &buf_size_v6,
|
||||
.buf_align = &mfc_buf_align_v6,
|
||||
.mclk_name = "aclk_333",
|
||||
.fw_name = "s5p-mfc-v6.fw",
|
||||
};
|
||||
|
||||
static struct platform_device_id mfc_driver_ids[] = {
|
||||
{
|
||||
.name = "s5p-mfc",
|
||||
.driver_data = (unsigned long)&mfc_drvdata_v5,
|
||||
}, {
|
||||
.name = "s5p-mfc-v5",
|
||||
.driver_data = (unsigned long)&mfc_drvdata_v5,
|
||||
}, {
|
||||
.name = "s5p-mfc-v6",
|
||||
.driver_data = (unsigned long)&mfc_drvdata_v6,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
|
||||
|
||||
static struct platform_driver s5p_mfc_driver = {
|
||||
.probe = s5p_mfc_probe,
|
||||
.remove = __devexit_p(s5p_mfc_remove),
|
||||
.probe = s5p_mfc_probe,
|
||||
.remove = __devexit_p(s5p_mfc_remove),
|
||||
.id_table = mfc_driver_ids,
|
||||
.driver = {
|
||||
.name = S5P_MFC_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -10,111 +10,20 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_cmd.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_cmd_v5.h"
|
||||
#include "s5p_mfc_cmd_v6.h"
|
||||
|
||||
/* This function is used to send a command to the MFC */
|
||||
static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
|
||||
struct s5p_mfc_cmd_args *args)
|
||||
static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
|
||||
|
||||
void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
int cur_cmd;
|
||||
unsigned long timeout;
|
||||
if (IS_MFCV6(dev))
|
||||
s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
|
||||
else
|
||||
s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
|
||||
/* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
mfc_err("Timeout while waiting for hardware\n");
|
||||
return -EIO;
|
||||
}
|
||||
cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
|
||||
} while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
|
||||
mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
|
||||
mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
|
||||
mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
|
||||
mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
|
||||
/* Issue the command */
|
||||
mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
|
||||
return 0;
|
||||
dev->mfc_cmds = s5p_mfc_cmds;
|
||||
}
|
||||
|
||||
/* Initialize the MFC */
|
||||
int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
h2r_args.arg[0] = dev->fw_size;
|
||||
return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
|
||||
}
|
||||
|
||||
/* Suspend the MFC hardware */
|
||||
int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
|
||||
}
|
||||
|
||||
/* Wake up the MFC hardware */
|
||||
int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
|
||||
}
|
||||
|
||||
|
||||
int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
int ret;
|
||||
|
||||
/* Preparing decoding - getting instance number */
|
||||
mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
|
||||
dev->curr_ctx = ctx->num;
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
h2r_args.arg[0] = ctx->codec_mode;
|
||||
h2r_args.arg[1] = 0; /* no crc & no pixelcache */
|
||||
h2r_args.arg[2] = ctx->ctx_ofs;
|
||||
h2r_args.arg[3] = ctx->ctx_size;
|
||||
ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
|
||||
&h2r_args);
|
||||
if (ret) {
|
||||
mfc_err("Failed to create a new instance\n");
|
||||
ctx->state = MFCINST_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
int ret;
|
||||
|
||||
if (ctx->state == MFCINST_FREE) {
|
||||
mfc_err("Instance already returned\n");
|
||||
ctx->state = MFCINST_ERROR;
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Closing decoding instance */
|
||||
mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
|
||||
dev->curr_ctx = ctx->num;
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
h2r_args.arg[0] = ctx->inst_no;
|
||||
ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
|
||||
&h2r_args);
|
||||
if (ret) {
|
||||
mfc_err("Failed to return an instance\n");
|
||||
ctx->state = MFCINST_ERROR;
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -21,10 +21,15 @@ struct s5p_mfc_cmd_args {
|
|||
unsigned int arg[MAX_H2R_ARG];
|
||||
};
|
||||
|
||||
int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
|
||||
int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
|
||||
int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
|
||||
int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx);
|
||||
int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx);
|
||||
struct s5p_mfc_hw_cmds {
|
||||
int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
|
||||
struct s5p_mfc_cmd_args *args);
|
||||
int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
|
||||
int (*sleep_cmd)(struct s5p_mfc_dev *dev);
|
||||
int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
|
||||
int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
|
||||
int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
|
||||
};
|
||||
|
||||
void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
|
||||
#endif /* S5P_MFC_CMD_H_ */
|
||||
|
|
|
|||
166
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
Normal file
166
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_cmd.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
|
||||
/* This function is used to send a command to the MFC */
|
||||
int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
|
||||
struct s5p_mfc_cmd_args *args)
|
||||
{
|
||||
int cur_cmd;
|
||||
unsigned long timeout;
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
|
||||
/* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
mfc_err("Timeout while waiting for hardware\n");
|
||||
return -EIO;
|
||||
}
|
||||
cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
|
||||
} while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
|
||||
mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
|
||||
mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
|
||||
mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
|
||||
mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
|
||||
/* Issue the command */
|
||||
mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize the MFC */
|
||||
int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
h2r_args.arg[0] = dev->fw_size;
|
||||
return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
|
||||
&h2r_args);
|
||||
}
|
||||
|
||||
/* Suspend the MFC hardware */
|
||||
int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
|
||||
}
|
||||
|
||||
/* Wake up the MFC hardware */
|
||||
int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
|
||||
&h2r_args);
|
||||
}
|
||||
|
||||
|
||||
int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
int ret;
|
||||
|
||||
/* Preparing decoding - getting instance number */
|
||||
mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
|
||||
dev->curr_ctx = ctx->num;
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
switch (ctx->codec_mode) {
|
||||
case S5P_MFC_CODEC_H264_DEC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_VC1_DEC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_MPEG4_DEC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_MPEG2_DEC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H263_DEC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_VC1RCV_DEC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H264_ENC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_MPEG4_ENC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H263_ENC:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
|
||||
break;
|
||||
default:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
|
||||
};
|
||||
h2r_args.arg[1] = 0; /* no crc & no pixelcache */
|
||||
h2r_args.arg[2] = ctx->ctx.ofs;
|
||||
h2r_args.arg[3] = ctx->ctx.size;
|
||||
ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
|
||||
&h2r_args);
|
||||
if (ret) {
|
||||
mfc_err("Failed to create a new instance\n");
|
||||
ctx->state = MFCINST_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
int ret;
|
||||
|
||||
if (ctx->state == MFCINST_FREE) {
|
||||
mfc_err("Instance already returned\n");
|
||||
ctx->state = MFCINST_ERROR;
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Closing decoding instance */
|
||||
mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
|
||||
dev->curr_ctx = ctx->num;
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
h2r_args.arg[0] = ctx->inst_no;
|
||||
ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
|
||||
&h2r_args);
|
||||
if (ret) {
|
||||
mfc_err("Failed to return an instance\n");
|
||||
ctx->state = MFCINST_ERROR;
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize cmd function pointers for MFC v5 */
|
||||
static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
|
||||
.cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
|
||||
.sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
|
||||
.sleep_cmd = s5p_mfc_sleep_cmd_v5,
|
||||
.wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
|
||||
.open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
|
||||
.close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
|
||||
};
|
||||
|
||||
struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
|
||||
{
|
||||
return &s5p_mfc_cmds_v5;
|
||||
}
|
||||
20
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
Normal file
20
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef S5P_MFC_CMD_V5_H_
|
||||
#define S5P_MFC_CMD_V5_H_
|
||||
|
||||
#include "s5p_mfc_common.h"
|
||||
|
||||
struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
|
||||
|
||||
#endif /* S5P_MFC_CMD_H_ */
|
||||
156
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
Normal file
156
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "s5p_mfc_common.h"
|
||||
|
||||
#include "s5p_mfc_cmd.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_intr.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
|
||||
int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
|
||||
struct s5p_mfc_cmd_args *args)
|
||||
{
|
||||
mfc_debug(2, "Issue the command: %d\n", cmd);
|
||||
|
||||
/* Reset RISC2HOST command */
|
||||
mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
|
||||
|
||||
/* Issue the command */
|
||||
mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
|
||||
mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
|
||||
|
||||
s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
|
||||
mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
|
||||
mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
|
||||
return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
|
||||
&h2r_args);
|
||||
}
|
||||
|
||||
int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
|
||||
&h2r_args);
|
||||
}
|
||||
|
||||
int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
|
||||
memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
|
||||
return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
|
||||
&h2r_args);
|
||||
}
|
||||
|
||||
/* Open a new instance and get its number */
|
||||
int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
int codec_type;
|
||||
|
||||
mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
|
||||
dev->curr_ctx = ctx->num;
|
||||
switch (ctx->codec_mode) {
|
||||
case S5P_MFC_CODEC_H264_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H264_MVC_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_VC1_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_MPEG4_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_MPEG2_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H263_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_VC1RCV_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_VP8_DEC:
|
||||
codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H264_ENC:
|
||||
codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H264_MVC_ENC:
|
||||
codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_MPEG4_ENC:
|
||||
codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_H263_ENC:
|
||||
codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
|
||||
break;
|
||||
default:
|
||||
codec_type = S5P_FIMV_CODEC_NONE_V6;
|
||||
};
|
||||
mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
|
||||
mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
|
||||
mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
|
||||
mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
|
||||
|
||||
return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
|
||||
&h2r_args);
|
||||
}
|
||||
|
||||
/* Close instance */
|
||||
int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
struct s5p_mfc_cmd_args h2r_args;
|
||||
int ret = 0;
|
||||
|
||||
dev->curr_ctx = ctx->num;
|
||||
if (ctx->state != MFCINST_FREE) {
|
||||
mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
|
||||
ret = s5p_mfc_cmd_host2risc_v6(dev,
|
||||
S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
|
||||
&h2r_args);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize cmd function pointers for MFC v6 */
|
||||
static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
|
||||
.cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
|
||||
.sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
|
||||
.sleep_cmd = s5p_mfc_sleep_cmd_v6,
|
||||
.wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
|
||||
.open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
|
||||
.close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
|
||||
};
|
||||
|
||||
struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
|
||||
{
|
||||
return &s5p_mfc_cmds_v6;
|
||||
}
|
||||
20
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
Normal file
20
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef S5P_MFC_CMD_V6_H_
|
||||
#define S5P_MFC_CMD_V6_H_
|
||||
|
||||
#include "s5p_mfc_common.h"
|
||||
|
||||
struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
|
||||
|
||||
#endif /* S5P_MFC_CMD_H_ */
|
||||
|
|
@ -16,13 +16,14 @@
|
|||
#ifndef S5P_MFC_COMMON_H_
|
||||
#define S5P_MFC_COMMON_H_
|
||||
|
||||
#include "regs-mfc.h"
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include "regs-mfc.h"
|
||||
#include "regs-mfc-v6.h"
|
||||
|
||||
/* Definitions related to MFC memory */
|
||||
|
||||
|
|
@ -30,17 +31,6 @@
|
|||
* while mmaping */
|
||||
#define DST_QUEUE_OFF_BASE (TASK_SIZE / 2)
|
||||
|
||||
/* Offset used by the hardware to store addresses */
|
||||
#define MFC_OFFSET_SHIFT 11
|
||||
|
||||
#define FIRMWARE_ALIGN 0x20000 /* 128KB */
|
||||
#define MFC_H264_CTX_BUF_SIZE 0x96000 /* 600KB per H264 instance */
|
||||
#define MFC_CTX_BUF_SIZE 0x2800 /* 10KB per instance */
|
||||
#define DESC_BUF_SIZE 0x20000 /* 128KB for DESC buffer */
|
||||
#define SHARED_BUF_SIZE 0x2000 /* 8KB for shared buffer */
|
||||
|
||||
#define DEF_CPB_SIZE 0x40000 /* 512KB */
|
||||
|
||||
#define MFC_BANK1_ALLOC_CTX 0
|
||||
#define MFC_BANK2_ALLOC_CTX 1
|
||||
|
||||
|
|
@ -74,7 +64,40 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
|
|||
#define MFC_ENC_CAP_PLANE_COUNT 1
|
||||
#define MFC_ENC_OUT_PLANE_COUNT 2
|
||||
#define STUFF_BYTE 4
|
||||
#define MFC_MAX_CTRLS 64
|
||||
#define MFC_MAX_CTRLS 70
|
||||
|
||||
#define S5P_MFC_CODEC_NONE -1
|
||||
#define S5P_MFC_CODEC_H264_DEC 0
|
||||
#define S5P_MFC_CODEC_H264_MVC_DEC 1
|
||||
#define S5P_MFC_CODEC_VC1_DEC 2
|
||||
#define S5P_MFC_CODEC_MPEG4_DEC 3
|
||||
#define S5P_MFC_CODEC_MPEG2_DEC 4
|
||||
#define S5P_MFC_CODEC_H263_DEC 5
|
||||
#define S5P_MFC_CODEC_VC1RCV_DEC 6
|
||||
#define S5P_MFC_CODEC_VP8_DEC 7
|
||||
|
||||
#define S5P_MFC_CODEC_H264_ENC 20
|
||||
#define S5P_MFC_CODEC_H264_MVC_ENC 21
|
||||
#define S5P_MFC_CODEC_MPEG4_ENC 22
|
||||
#define S5P_MFC_CODEC_H263_ENC 23
|
||||
|
||||
#define S5P_MFC_R2H_CMD_EMPTY 0
|
||||
#define S5P_MFC_R2H_CMD_SYS_INIT_RET 1
|
||||
#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET 2
|
||||
#define S5P_MFC_R2H_CMD_SEQ_DONE_RET 3
|
||||
#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET 4
|
||||
#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET 6
|
||||
#define S5P_MFC_R2H_CMD_SLEEP_RET 7
|
||||
#define S5P_MFC_R2H_CMD_WAKEUP_RET 8
|
||||
#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET 9
|
||||
#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET 10
|
||||
#define S5P_MFC_R2H_CMD_NAL_ABORT_RET 11
|
||||
#define S5P_MFC_R2H_CMD_FW_STATUS_RET 12
|
||||
#define S5P_MFC_R2H_CMD_FRAME_DONE_RET 13
|
||||
#define S5P_MFC_R2H_CMD_FIELD_DONE_RET 14
|
||||
#define S5P_MFC_R2H_CMD_SLICE_DONE_RET 15
|
||||
#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET 16
|
||||
#define S5P_MFC_R2H_CMD_ERR_RET 32
|
||||
|
||||
#define mfc_read(dev, offset) readl(dev->regs_base + (offset))
|
||||
#define mfc_write(dev, data, offset) writel((data), dev->regs_base + \
|
||||
|
|
@ -177,6 +200,58 @@ struct s5p_mfc_pm {
|
|||
struct device *device;
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size_v5 {
|
||||
unsigned int h264_ctx;
|
||||
unsigned int non_h264_ctx;
|
||||
unsigned int dsc;
|
||||
unsigned int shm;
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size_v6 {
|
||||
unsigned int dev_ctx;
|
||||
unsigned int h264_dec_ctx;
|
||||
unsigned int other_dec_ctx;
|
||||
unsigned int h264_enc_ctx;
|
||||
unsigned int other_enc_ctx;
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size {
|
||||
unsigned int fw;
|
||||
unsigned int cpb;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_align {
|
||||
unsigned int base;
|
||||
};
|
||||
|
||||
struct s5p_mfc_variant {
|
||||
unsigned int version;
|
||||
unsigned int port_num;
|
||||
struct s5p_mfc_buf_size *buf_size;
|
||||
struct s5p_mfc_buf_align *buf_align;
|
||||
char *mclk_name;
|
||||
char *fw_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct s5p_mfc_priv_buf - represents internal used buffer
|
||||
* @alloc: allocation-specific context for each buffer
|
||||
* (videobuf2 allocator)
|
||||
* @ofs: offset of each buffer, will be used for MFC
|
||||
* @virt: kernel virtual address, only valid when the
|
||||
* buffer accessed by driver
|
||||
* @dma: DMA address, only valid when kernel DMA API used
|
||||
* @size: size of the buffer
|
||||
*/
|
||||
struct s5p_mfc_priv_buf {
|
||||
void *alloc;
|
||||
unsigned long ofs;
|
||||
void *virt;
|
||||
dma_addr_t dma;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct s5p_mfc_dev - The struct containing driver internal parameters.
|
||||
*
|
||||
|
|
@ -191,6 +266,7 @@ struct s5p_mfc_pm {
|
|||
* @dec_ctrl_handler: control framework handler for decoding
|
||||
* @enc_ctrl_handler: control framework handler for encoding
|
||||
* @pm: power management control
|
||||
* @variant: MFC hardware variant information
|
||||
* @num_inst: couter of active MFC instances
|
||||
* @irqlock: lock for operations on videobuf2 queues
|
||||
* @condlock: lock for changing/checking if a context is ready to be
|
||||
|
|
@ -212,6 +288,10 @@ struct s5p_mfc_pm {
|
|||
* @watchdog_work: worker for the watchdog
|
||||
* @alloc_ctx: videobuf2 allocator contexts for two memory banks
|
||||
* @enter_suspend: flag set when entering suspend
|
||||
* @ctx_buf: common context memory (MFCv6)
|
||||
* @warn_start: hardware error code from which warnings start
|
||||
* @mfc_ops: ops structure holding HW operation function pointers
|
||||
* @mfc_cmds: cmd structure holding HW commands function pointers
|
||||
*
|
||||
*/
|
||||
struct s5p_mfc_dev {
|
||||
|
|
@ -226,6 +306,7 @@ struct s5p_mfc_dev {
|
|||
struct v4l2_ctrl_handler dec_ctrl_handler;
|
||||
struct v4l2_ctrl_handler enc_ctrl_handler;
|
||||
struct s5p_mfc_pm pm;
|
||||
struct s5p_mfc_variant *variant;
|
||||
int num_inst;
|
||||
spinlock_t irqlock; /* lock when operating on videobuf2 queues */
|
||||
spinlock_t condlock; /* lock when changing/checking if a context is
|
||||
|
|
@ -248,6 +329,11 @@ struct s5p_mfc_dev {
|
|||
struct work_struct watchdog_work;
|
||||
void *alloc_ctx[2];
|
||||
unsigned long enter_suspend;
|
||||
|
||||
struct s5p_mfc_priv_buf ctx_buf;
|
||||
int warn_start;
|
||||
struct s5p_mfc_hw_ops *mfc_ops;
|
||||
struct s5p_mfc_hw_cmds *mfc_cmds;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -262,7 +348,6 @@ struct s5p_mfc_h264_enc_params {
|
|||
u8 max_ref_pic;
|
||||
u8 num_ref_pic_4p;
|
||||
int _8x8_transform;
|
||||
int rc_mb;
|
||||
int rc_mb_dark;
|
||||
int rc_mb_smooth;
|
||||
int rc_mb_static;
|
||||
|
|
@ -281,6 +366,23 @@ struct s5p_mfc_h264_enc_params {
|
|||
enum v4l2_mpeg_video_h264_level level_v4l2;
|
||||
int level;
|
||||
u16 cpb_size;
|
||||
int interlace;
|
||||
u8 hier_qp;
|
||||
u8 hier_qp_type;
|
||||
u8 hier_qp_layer;
|
||||
u8 hier_qp_layer_qp[7];
|
||||
u8 sei_frame_packing;
|
||||
u8 sei_fp_curr_frame_0;
|
||||
u8 sei_fp_arrangement_type;
|
||||
|
||||
u8 fmo;
|
||||
u8 fmo_map_type;
|
||||
u8 fmo_slice_grp;
|
||||
u8 fmo_chg_dir;
|
||||
u32 fmo_chg_rate;
|
||||
u32 fmo_run_len[4];
|
||||
u8 aso;
|
||||
u32 aso_slice_order[8];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -319,9 +421,11 @@ struct s5p_mfc_enc_params {
|
|||
u8 pad_cb;
|
||||
u8 pad_cr;
|
||||
int rc_frame;
|
||||
int rc_mb;
|
||||
u32 rc_bitrate;
|
||||
u16 rc_reaction_coeff;
|
||||
u16 vbv_size;
|
||||
u32 vbv_delay;
|
||||
|
||||
enum v4l2_mpeg_video_header_mode seq_hdr_mode;
|
||||
enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
|
||||
|
|
@ -330,7 +434,6 @@ struct s5p_mfc_enc_params {
|
|||
u8 num_b_frame;
|
||||
u32 rc_framerate_num;
|
||||
u32 rc_framerate_denom;
|
||||
int interlace;
|
||||
|
||||
union {
|
||||
struct s5p_mfc_h264_enc_params h264;
|
||||
|
|
@ -388,6 +491,8 @@ struct s5p_mfc_codec_ops {
|
|||
* decoding buffer
|
||||
* @dpb_flush_flag: flag used to indicate that a DPB buffers are being
|
||||
* flushed
|
||||
* @head_processed: flag mentioning whether the header data is processed
|
||||
* completely or not
|
||||
* @bank1_buf: handle to memory allocated for temporary buffers from
|
||||
* memory bank 1
|
||||
* @bank1_phys: address of the temporary buffers from memory bank 1
|
||||
|
|
@ -412,19 +517,20 @@ struct s5p_mfc_codec_ops {
|
|||
* @display_delay_enable: display delay for H264 enable flag
|
||||
* @after_packed_pb: flag used to track buffer when stream is in
|
||||
* Packed PB format
|
||||
* @sei_fp_parse: enable/disable parsing of frame packing SEI information
|
||||
* @dpb_count: count of the DPB buffers required by MFC hw
|
||||
* @total_dpb_count: count of DPB buffers with additional buffers
|
||||
* requested by the application
|
||||
* @ctx_buf: handle to the memory associated with this context
|
||||
* @ctx_phys: address of the memory associated with this context
|
||||
* @ctx_size: size of the memory associated with this context
|
||||
* @desc_buf: description buffer for decoding handle
|
||||
* @desc_phys: description buffer for decoding address
|
||||
* @shm_alloc: handle for the shared memory buffer
|
||||
* @shm: virtual address for the shared memory buffer
|
||||
* @shm_ofs: address offset for shared memory
|
||||
* @ctx: context buffer information
|
||||
* @dsc: descriptor buffer information
|
||||
* @shm: shared memory buffer information
|
||||
* @mv_count: number of MV buffers allocated for decoding
|
||||
* @enc_params: encoding parameters for MFC
|
||||
* @enc_dst_buf_size: size of the buffers for encoder output
|
||||
* @luma_dpb_size: dpb buffer size for luma
|
||||
* @chroma_dpb_size: dpb buffer size for chroma
|
||||
* @me_buffer_size: size of the motion estimation buffer
|
||||
* @tmv_buffer_size: size of temporal predictor motion vector buffer
|
||||
* @frame_type: used to force the type of the next encoded frame
|
||||
* @ref_queue: list of the reference buffers for encoding
|
||||
* @ref_queue_cnt: number of the buffers in the reference list
|
||||
|
|
@ -473,6 +579,7 @@ struct s5p_mfc_ctx {
|
|||
unsigned long consumed_stream;
|
||||
|
||||
unsigned int dpb_flush_flag;
|
||||
unsigned int head_processed;
|
||||
|
||||
/* Buffers */
|
||||
void *bank1_buf;
|
||||
|
|
@ -502,37 +609,41 @@ struct s5p_mfc_ctx {
|
|||
int display_delay;
|
||||
int display_delay_enable;
|
||||
int after_packed_pb;
|
||||
int sei_fp_parse;
|
||||
|
||||
int dpb_count;
|
||||
int total_dpb_count;
|
||||
|
||||
int mv_count;
|
||||
/* Buffers */
|
||||
void *ctx_buf;
|
||||
size_t ctx_phys;
|
||||
size_t ctx_ofs;
|
||||
size_t ctx_size;
|
||||
|
||||
void *desc_buf;
|
||||
size_t desc_phys;
|
||||
|
||||
|
||||
void *shm_alloc;
|
||||
void *shm;
|
||||
size_t shm_ofs;
|
||||
struct s5p_mfc_priv_buf ctx;
|
||||
struct s5p_mfc_priv_buf dsc;
|
||||
struct s5p_mfc_priv_buf shm;
|
||||
|
||||
struct s5p_mfc_enc_params enc_params;
|
||||
|
||||
size_t enc_dst_buf_size;
|
||||
size_t luma_dpb_size;
|
||||
size_t chroma_dpb_size;
|
||||
size_t me_buffer_size;
|
||||
size_t tmv_buffer_size;
|
||||
|
||||
enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
|
||||
|
||||
struct list_head ref_queue;
|
||||
unsigned int ref_queue_cnt;
|
||||
|
||||
enum v4l2_mpeg_video_multi_slice_mode slice_mode;
|
||||
union {
|
||||
unsigned int mb;
|
||||
unsigned int bits;
|
||||
} slice_size;
|
||||
|
||||
struct s5p_mfc_codec_ops *c_ops;
|
||||
|
||||
struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
unsigned int frame_tag;
|
||||
size_t scratch_buf_size;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -565,6 +676,9 @@ struct mfc_control {
|
|||
__u8 is_volatile;
|
||||
};
|
||||
|
||||
/* Macro for making hardware specific calls */
|
||||
#define s5p_mfc_hw_call(f, op, args...) \
|
||||
((f && f->op) ? f->op(args) : -ENODEV)
|
||||
|
||||
#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
|
||||
#define ctrl_to_ctx(__ctrl) \
|
||||
|
|
@ -575,4 +689,9 @@ void set_work_bit(struct s5p_mfc_ctx *ctx);
|
|||
void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
|
||||
void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
#define HAS_PORTNUM(dev) (dev ? (dev->variant ? \
|
||||
(dev->variant->port_num ? 1 : 0) : 0) : 0)
|
||||
#define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0)
|
||||
#define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 : 0)
|
||||
|
||||
#endif /* S5P_MFC_COMMON_H_ */
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/sched.h>
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_cmd.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_intr.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
#include "s5p_mfc_pm.h"
|
||||
|
||||
static void *s5p_mfc_bitproc_buf;
|
||||
|
|
@ -37,13 +37,19 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
|
|||
/* Firmare has to be present as a separate file or compiled
|
||||
* into kernel. */
|
||||
mfc_debug_enter();
|
||||
|
||||
err = request_firmware((const struct firmware **)&fw_blob,
|
||||
"s5p-mfc.fw", dev->v4l2_dev.dev);
|
||||
dev->variant->fw_name, dev->v4l2_dev.dev);
|
||||
if (err != 0) {
|
||||
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
|
||||
dev->fw_size = dev->variant->buf_size->fw;
|
||||
if (fw_blob->size > dev->fw_size) {
|
||||
mfc_err("MFC firmware is too big to be loaded\n");
|
||||
release_firmware(fw_blob);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (s5p_mfc_bitproc_buf) {
|
||||
mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
|
||||
release_firmware(fw_blob);
|
||||
|
|
@ -77,32 +83,37 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
|
|||
return -EIO;
|
||||
}
|
||||
dev->bank1 = s5p_mfc_bitproc_phys;
|
||||
b_base = vb2_dma_contig_memops.alloc(
|
||||
dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER);
|
||||
if (IS_ERR(b_base)) {
|
||||
vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
|
||||
s5p_mfc_bitproc_phys = 0;
|
||||
s5p_mfc_bitproc_buf = NULL;
|
||||
mfc_err("Allocating bank2 base failed\n");
|
||||
release_firmware(fw_blob);
|
||||
return -ENOMEM;
|
||||
if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
|
||||
b_base = vb2_dma_contig_memops.alloc(
|
||||
dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
|
||||
1 << MFC_BASE_ALIGN_ORDER);
|
||||
if (IS_ERR(b_base)) {
|
||||
vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
|
||||
s5p_mfc_bitproc_phys = 0;
|
||||
s5p_mfc_bitproc_buf = NULL;
|
||||
mfc_err("Allocating bank2 base failed\n");
|
||||
release_firmware(fw_blob);
|
||||
return -ENOMEM;
|
||||
}
|
||||
bank2_base_phys = s5p_mfc_mem_cookie(
|
||||
dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
|
||||
vb2_dma_contig_memops.put(b_base);
|
||||
if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
|
||||
mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
|
||||
vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
|
||||
s5p_mfc_bitproc_phys = 0;
|
||||
s5p_mfc_bitproc_buf = NULL;
|
||||
release_firmware(fw_blob);
|
||||
return -EIO;
|
||||
}
|
||||
/* Valid buffers passed to MFC encoder with LAST_FRAME command
|
||||
* should not have address of bank2 - MFC will treat it as a null frame.
|
||||
* To avoid such situation we set bank2 address below the pool address.
|
||||
*/
|
||||
dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
|
||||
} else {
|
||||
dev->bank2 = dev->bank1;
|
||||
}
|
||||
bank2_base_phys = s5p_mfc_mem_cookie(
|
||||
dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
|
||||
vb2_dma_contig_memops.put(b_base);
|
||||
if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
|
||||
mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
|
||||
vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
|
||||
s5p_mfc_bitproc_phys = 0;
|
||||
s5p_mfc_bitproc_buf = NULL;
|
||||
release_firmware(fw_blob);
|
||||
return -EIO;
|
||||
}
|
||||
/* Valid buffers passed to MFC encoder with LAST_FRAME command
|
||||
* should not have address of bank2 - MFC will treat it as a null frame.
|
||||
* To avoid such situation we set bank2 address below the pool address.
|
||||
*/
|
||||
dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
|
||||
memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
|
||||
wmb();
|
||||
release_firmware(fw_blob);
|
||||
|
|
@ -119,8 +130,9 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
|
|||
/* Firmare has to be present as a separate file or compiled
|
||||
* into kernel. */
|
||||
mfc_debug_enter();
|
||||
|
||||
err = request_firmware((const struct firmware **)&fw_blob,
|
||||
"s5p-mfc.fw", dev->v4l2_dev.dev);
|
||||
dev->variant->fw_name, dev->v4l2_dev.dev);
|
||||
if (err != 0) {
|
||||
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -161,46 +173,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
|
|||
{
|
||||
unsigned int mc_status;
|
||||
unsigned long timeout;
|
||||
int i;
|
||||
|
||||
mfc_debug_enter();
|
||||
/* Stop procedure */
|
||||
/* reset RISC */
|
||||
mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
|
||||
/* All reset except for MC */
|
||||
mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
|
||||
mdelay(10);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
|
||||
/* Check MC status */
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
mfc_err("Timeout while resetting MFC\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (IS_MFCV6(dev)) {
|
||||
/* Reset IP */
|
||||
/* except RISC, reset */
|
||||
mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
|
||||
/* reset release */
|
||||
mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
|
||||
|
||||
mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
|
||||
/* Zero Initialization of MFC registers */
|
||||
mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
|
||||
mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
|
||||
mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
|
||||
|
||||
} while (mc_status & 0x3);
|
||||
for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
|
||||
mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
|
||||
|
||||
/* Reset */
|
||||
mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
|
||||
mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
|
||||
mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
|
||||
} else {
|
||||
/* Stop procedure */
|
||||
/* reset RISC */
|
||||
mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
|
||||
/* All reset except for MC */
|
||||
mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
|
||||
mdelay(10);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
|
||||
/* Check MC status */
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
mfc_err("Timeout while resetting MFC\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
|
||||
|
||||
} while (mc_status & 0x3);
|
||||
|
||||
mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
|
||||
mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
|
||||
}
|
||||
|
||||
mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
|
||||
mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
|
||||
mfc_debug_leave();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
|
||||
mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
|
||||
mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
|
||||
if (IS_MFCV6(dev)) {
|
||||
mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6);
|
||||
mfc_debug(2, "Base Address : %08x\n", dev->bank1);
|
||||
} else {
|
||||
mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
|
||||
mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
|
||||
mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
|
||||
dev->bank1, dev->bank2);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
|
||||
mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
|
||||
mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
|
||||
mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
|
||||
if (IS_MFCV6(dev)) {
|
||||
/* Zero initialization should be done before RESET.
|
||||
* Nothing to do here. */
|
||||
} else {
|
||||
mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
|
||||
mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
|
||||
mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
|
||||
mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize hardware */
|
||||
|
|
@ -228,9 +275,12 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
|
|||
s5p_mfc_clear_cmds(dev);
|
||||
/* 3. Release reset signal to the RISC */
|
||||
s5p_mfc_clean_dev_int_flags(dev);
|
||||
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
|
||||
if (IS_MFCV6(dev))
|
||||
mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
|
||||
else
|
||||
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
|
||||
mfc_debug(2, "Will now wait for completion of firmware transfer\n");
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
|
||||
mfc_err("Failed to load firmware\n");
|
||||
s5p_mfc_reset(dev);
|
||||
s5p_mfc_clock_off();
|
||||
|
|
@ -238,7 +288,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
|
|||
}
|
||||
s5p_mfc_clean_dev_int_flags(dev);
|
||||
/* 4. Initialize firmware */
|
||||
ret = s5p_mfc_sys_init_cmd(dev);
|
||||
ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
|
||||
if (ret) {
|
||||
mfc_err("Failed to send command to MFC - timeout\n");
|
||||
s5p_mfc_reset(dev);
|
||||
|
|
@ -246,7 +296,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
|
|||
return ret;
|
||||
}
|
||||
mfc_debug(2, "Ok, now will write a command to init the system\n");
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
|
||||
mfc_err("Failed to load firmware\n");
|
||||
s5p_mfc_reset(dev);
|
||||
s5p_mfc_clock_off();
|
||||
|
|
@ -254,7 +304,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
|
|||
}
|
||||
dev->int_cond = 0;
|
||||
if (dev->int_err != 0 || dev->int_type !=
|
||||
S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
|
||||
S5P_MFC_R2H_CMD_SYS_INIT_RET) {
|
||||
/* Failure. */
|
||||
mfc_err("Failed to init firmware - error: %d int: %d\n",
|
||||
dev->int_err, dev->int_type);
|
||||
|
|
@ -262,7 +312,11 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
|
|||
s5p_mfc_clock_off();
|
||||
return -EIO;
|
||||
}
|
||||
ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
|
||||
if (IS_MFCV6(dev))
|
||||
ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
|
||||
else
|
||||
ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
|
||||
|
||||
mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
|
||||
(ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
|
||||
s5p_mfc_clock_off();
|
||||
|
|
@ -271,6 +325,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
|
|||
}
|
||||
|
||||
|
||||
/* Deinitialize hardware */
|
||||
void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
s5p_mfc_clock_on();
|
||||
|
||||
s5p_mfc_reset(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
|
||||
|
||||
s5p_mfc_clock_off();
|
||||
}
|
||||
|
||||
int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -278,19 +343,19 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
|
|||
mfc_debug_enter();
|
||||
s5p_mfc_clock_on();
|
||||
s5p_mfc_clean_dev_int_flags(dev);
|
||||
ret = s5p_mfc_sleep_cmd(dev);
|
||||
ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
|
||||
if (ret) {
|
||||
mfc_err("Failed to send command to MFC - timeout\n");
|
||||
return ret;
|
||||
}
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
|
||||
mfc_err("Failed to sleep\n");
|
||||
return -EIO;
|
||||
}
|
||||
s5p_mfc_clock_off();
|
||||
dev->int_cond = 0;
|
||||
if (dev->int_err != 0 || dev->int_type !=
|
||||
S5P_FIMV_R2H_CMD_SLEEP_RET) {
|
||||
S5P_MFC_R2H_CMD_SLEEP_RET) {
|
||||
/* Failure. */
|
||||
mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
|
||||
dev->int_type);
|
||||
|
|
@ -320,22 +385,25 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
|
|||
s5p_mfc_clear_cmds(dev);
|
||||
s5p_mfc_clean_dev_int_flags(dev);
|
||||
/* 3. Initialize firmware */
|
||||
ret = s5p_mfc_wakeup_cmd(dev);
|
||||
ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
|
||||
if (ret) {
|
||||
mfc_err("Failed to send command to MFC - timeout\n");
|
||||
return ret;
|
||||
}
|
||||
/* 4. Release reset signal to the RISC */
|
||||
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
|
||||
if (IS_MFCV6(dev))
|
||||
mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
|
||||
else
|
||||
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
|
||||
mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
|
||||
if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
|
||||
mfc_err("Failed to load firmware\n");
|
||||
return -EIO;
|
||||
}
|
||||
s5p_mfc_clock_off();
|
||||
dev->int_cond = 0;
|
||||
if (dev->int_err != 0 || dev->int_type !=
|
||||
S5P_FIMV_R2H_CMD_WAKEUP_RET) {
|
||||
S5P_MFC_R2H_CMD_WAKEUP_RET) {
|
||||
/* Failure. */
|
||||
mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
|
||||
dev->int_type);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
|
|||
int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
|
||||
|
||||
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
|
||||
void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
|
||||
|
||||
int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
|
||||
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
|
||||
|
|
|
|||
|
|
@ -23,85 +23,114 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_dec.h"
|
||||
#include "s5p_mfc_intr.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
#include "s5p_mfc_pm.h"
|
||||
#include "s5p_mfc_shm.h"
|
||||
|
||||
#define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264
|
||||
#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT_16X16
|
||||
|
||||
static struct s5p_mfc_fmt formats[] = {
|
||||
{
|
||||
.name = "4:2:0 2 Planes 64x32 Tiles",
|
||||
.fourcc = V4L2_PIX_FMT_NV12MT,
|
||||
.codec_mode = S5P_FIMV_CODEC_NONE,
|
||||
.name = "4:2:0 2 Planes 16x16 Tiles",
|
||||
.fourcc = V4L2_PIX_FMT_NV12MT_16X16,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "4:2:0 2 Planes",
|
||||
.fourcc = V4L2_PIX_FMT_NV12M,
|
||||
.codec_mode = S5P_FIMV_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "H264 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H264,
|
||||
.codec_mode = S5P_FIMV_CODEC_H264_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "4:2:0 2 Planes 64x32 Tiles",
|
||||
.fourcc = V4L2_PIX_FMT_NV12MT,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "H263 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H263,
|
||||
.codec_mode = S5P_FIMV_CODEC_H263_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "4:2:0 2 Planes Y/CbCr",
|
||||
.fourcc = V4L2_PIX_FMT_NV12M,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "MPEG1 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG1,
|
||||
.codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "4:2:0 2 Planes Y/CrCb",
|
||||
.fourcc = V4L2_PIX_FMT_NV21M,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "MPEG2 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG2,
|
||||
.codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "H264 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H264,
|
||||
.codec_mode = S5P_MFC_CODEC_H264_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "MPEG4 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG4,
|
||||
.codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "H264/MVC Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H264_MVC,
|
||||
.codec_mode = S5P_MFC_CODEC_H264_MVC_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "XviD Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_XVID,
|
||||
.codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "H263 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H263,
|
||||
.codec_mode = S5P_MFC_CODEC_H263_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "VC1 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
|
||||
.codec_mode = S5P_FIMV_CODEC_VC1_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "MPEG1 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG1,
|
||||
.codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "VC1 RCV Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
|
||||
.codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
.name = "MPEG2 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG2,
|
||||
.codec_mode = S5P_MFC_CODEC_MPEG2_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "MPEG4 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG4,
|
||||
.codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "XviD Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_XVID,
|
||||
.codec_mode = S5P_MFC_CODEC_MPEG4_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "VC1 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
|
||||
.codec_mode = S5P_MFC_CODEC_VC1_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "VC1 RCV Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
|
||||
.codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "VP8 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_VP8,
|
||||
.codec_mode = S5P_MFC_CODEC_VP8_DEC,
|
||||
.type = MFC_FMT_DEC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -297,7 +326,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
/* If the MFC is parsing the header,
|
||||
* so wait until it is finished */
|
||||
s5p_mfc_clean_ctx_int_flags(ctx);
|
||||
s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET,
|
||||
s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
|
||||
0);
|
||||
}
|
||||
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
|
||||
|
|
@ -342,21 +371,36 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
/* Try format */
|
||||
static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = video_drvdata(file);
|
||||
struct s5p_mfc_fmt *fmt;
|
||||
|
||||
if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
mfc_err("This node supports decoding only\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
fmt = find_format(f, MFC_FMT_DEC);
|
||||
if (!fmt) {
|
||||
mfc_err("Unsupported format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (fmt->type != MFC_FMT_DEC) {
|
||||
mfc_err("\n");
|
||||
return -EINVAL;
|
||||
mfc_debug(2, "Type is %d\n", f->type);
|
||||
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
fmt = find_format(f, MFC_FMT_DEC);
|
||||
if (!fmt) {
|
||||
mfc_err("Unsupported format for source.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
|
||||
fmt = find_format(f, MFC_FMT_RAW);
|
||||
if (!fmt) {
|
||||
mfc_err("Unsupported format for destination.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
} else if (!IS_MFCV6(dev) &&
|
||||
(fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -379,8 +423,29 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
|
||||
fmt = find_format(f, MFC_FMT_RAW);
|
||||
if (!fmt) {
|
||||
mfc_err("Unsupported format for source.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
} else if (IS_MFCV6(dev) &&
|
||||
(fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ctx->dst_fmt = fmt;
|
||||
mfc_debug_leave();
|
||||
return ret;
|
||||
} else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
mfc_err("Wrong type error for S_FMT : %d", f->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
fmt = find_format(f, MFC_FMT_DEC);
|
||||
if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
|
||||
if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
|
||||
mfc_err("Unknown codec\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
|
@ -391,6 +456,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ctx->src_fmt = fmt;
|
||||
ctx->codec_mode = fmt->codec_mode;
|
||||
mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
|
||||
|
|
@ -476,7 +545,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
|
|||
return -ENOMEM;
|
||||
}
|
||||
ctx->total_dpb_count = reqbufs->count;
|
||||
ret = s5p_mfc_alloc_codec_buffers(ctx);
|
||||
ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
|
||||
if (ret) {
|
||||
mfc_err("Failed to allocate decoding buffers\n");
|
||||
reqbufs->count = 0;
|
||||
|
|
@ -492,15 +561,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
|
|||
reqbufs->count = 0;
|
||||
s5p_mfc_clock_on();
|
||||
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
|
||||
s5p_mfc_release_codec_buffers(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
|
||||
ctx);
|
||||
s5p_mfc_clock_off();
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
s5p_mfc_wait_for_done_ctx(ctx,
|
||||
S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
|
||||
S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -582,18 +652,22 @@ static int vidioc_streamon(struct file *file, void *priv,
|
|||
ctx->src_bufs_cnt = 0;
|
||||
ctx->capture_state = QUEUE_FREE;
|
||||
ctx->output_state = QUEUE_FREE;
|
||||
s5p_mfc_alloc_instance_buffer(ctx);
|
||||
s5p_mfc_alloc_dec_temp_buffers(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer,
|
||||
ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers,
|
||||
ctx);
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_clean_ctx_int_flags(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
|
||||
if (s5p_mfc_wait_for_done_ctx(ctx,
|
||||
S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
|
||||
S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
|
||||
/* Error or timeout */
|
||||
mfc_err("Error getting instance from hardware\n");
|
||||
s5p_mfc_release_instance_buffer(ctx);
|
||||
s5p_mfc_release_dec_desc_buffer(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops,
|
||||
release_instance_buffer, ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops,
|
||||
release_dec_desc_buffer, ctx);
|
||||
return -EIO;
|
||||
}
|
||||
mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
|
||||
|
|
@ -662,7 +736,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
|
|||
/* Should wait for the header to be parsed */
|
||||
s5p_mfc_clean_ctx_int_flags(ctx);
|
||||
s5p_mfc_wait_for_done_ctx(ctx,
|
||||
S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0);
|
||||
S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
|
||||
if (ctx->state >= MFCINST_HEAD_PARSED &&
|
||||
ctx->state < MFCINST_ABORT) {
|
||||
ctrl->val = ctx->dpb_count;
|
||||
|
|
@ -686,6 +760,7 @@ static int vidioc_g_crop(struct file *file, void *priv,
|
|||
struct v4l2_crop *cr)
|
||||
{
|
||||
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
u32 left, right, top, bottom;
|
||||
|
||||
if (ctx->state != MFCINST_HEAD_PARSED &&
|
||||
|
|
@ -695,10 +770,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
|
||||
left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
|
||||
left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
|
||||
right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
|
||||
left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
|
||||
top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
|
||||
top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
|
||||
bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
|
||||
top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
|
||||
cr->c.left = left;
|
||||
|
|
@ -749,6 +824,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
|
|||
void *allocators[])
|
||||
{
|
||||
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
|
||||
/* Video output for decoding (source)
|
||||
* this can be set after getting an instance */
|
||||
|
|
@ -784,7 +860,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
|
|||
vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
|
||||
psize[0] = ctx->luma_size;
|
||||
psize[1] = ctx->chroma_size;
|
||||
allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
|
||||
|
||||
if (IS_MFCV6(dev))
|
||||
allocators[0] =
|
||||
ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
|
||||
else
|
||||
allocators[0] =
|
||||
ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
|
||||
allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
|
||||
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
|
||||
ctx->state == MFCINST_INIT) {
|
||||
|
|
@ -876,7 +958,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
|
|||
/* If context is ready then dev = work->data;schedule it to run */
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -892,19 +974,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
|
|||
dev->curr_ctx == ctx->num && dev->hw_lock) {
|
||||
ctx->state = MFCINST_ABORT;
|
||||
s5p_mfc_wait_for_done_ctx(ctx,
|
||||
S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0);
|
||||
S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
|
||||
aborted = 1;
|
||||
}
|
||||
spin_lock_irqsave(&dev->irqlock, flags);
|
||||
if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
|
||||
s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
|
||||
&ctx->vq_dst);
|
||||
INIT_LIST_HEAD(&ctx->dst_queue);
|
||||
ctx->dst_queue_cnt = 0;
|
||||
ctx->dpb_flush_flag = 1;
|
||||
ctx->dec_dst_flag = 0;
|
||||
}
|
||||
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
|
||||
&ctx->vq_src);
|
||||
INIT_LIST_HEAD(&ctx->src_queue);
|
||||
ctx->src_queue_cnt = 0;
|
||||
}
|
||||
|
|
@ -944,7 +1028,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
|
|||
}
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
}
|
||||
|
||||
static struct vb2_ops s5p_mfc_dec_qops = {
|
||||
|
|
@ -1028,3 +1112,13 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
|
|||
ctx->ctrls[i] = NULL;
|
||||
}
|
||||
|
||||
void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct v4l2_format f;
|
||||
f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC;
|
||||
ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
|
||||
f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC;
|
||||
ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
|
||||
mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
|
||||
(unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
|
|||
struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
|
||||
int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
#endif /* S5P_MFC_DEC_H_ */
|
||||
|
|
|
|||
|
|
@ -25,48 +25,64 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_enc.h"
|
||||
#include "s5p_mfc_intr.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
|
||||
#define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12MT
|
||||
#define DEF_DST_FMT_ENC V4L2_PIX_FMT_H264
|
||||
|
||||
static struct s5p_mfc_fmt formats[] = {
|
||||
{
|
||||
.name = "4:2:0 2 Planes 64x32 Tiles",
|
||||
.fourcc = V4L2_PIX_FMT_NV12MT,
|
||||
.codec_mode = S5P_FIMV_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
.name = "4:2:0 2 Planes 16x16 Tiles",
|
||||
.fourcc = V4L2_PIX_FMT_NV12MT_16X16,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "4:2:0 2 Planes",
|
||||
.fourcc = V4L2_PIX_FMT_NV12M,
|
||||
.codec_mode = S5P_FIMV_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
.name = "4:2:0 2 Planes 64x32 Tiles",
|
||||
.fourcc = V4L2_PIX_FMT_NV12MT,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "H264 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H264,
|
||||
.codec_mode = S5P_FIMV_CODEC_H264_ENC,
|
||||
.type = MFC_FMT_ENC,
|
||||
.num_planes = 1,
|
||||
.name = "4:2:0 2 Planes Y/CbCr",
|
||||
.fourcc = V4L2_PIX_FMT_NV12M,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "MPEG4 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG4,
|
||||
.codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
|
||||
.type = MFC_FMT_ENC,
|
||||
.num_planes = 1,
|
||||
.name = "4:2:0 2 Planes Y/CrCb",
|
||||
.fourcc = V4L2_PIX_FMT_NV21M,
|
||||
.codec_mode = S5P_MFC_CODEC_NONE,
|
||||
.type = MFC_FMT_RAW,
|
||||
.num_planes = 2,
|
||||
},
|
||||
{
|
||||
.name = "H263 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H263,
|
||||
.codec_mode = S5P_FIMV_CODEC_H263_ENC,
|
||||
.type = MFC_FMT_ENC,
|
||||
.num_planes = 1,
|
||||
.name = "H264 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H264,
|
||||
.codec_mode = S5P_MFC_CODEC_H264_ENC,
|
||||
.type = MFC_FMT_ENC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "MPEG4 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_MPEG4,
|
||||
.codec_mode = S5P_MFC_CODEC_MPEG4_ENC,
|
||||
.type = MFC_FMT_ENC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
{
|
||||
.name = "H263 Encoded Stream",
|
||||
.fourcc = V4L2_PIX_FMT_H263,
|
||||
.codec_mode = S5P_MFC_CODEC_H263_ENC,
|
||||
.type = MFC_FMT_ENC,
|
||||
.num_planes = 1,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -574,7 +590,8 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
|
|||
if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
|
||||
return 1;
|
||||
/* context is ready to encode a frame */
|
||||
if (ctx->state == MFCINST_RUNNING &&
|
||||
if ((ctx->state == MFCINST_RUNNING ||
|
||||
ctx->state == MFCINST_HEAD_PARSED) &&
|
||||
ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
|
||||
return 1;
|
||||
/* context is ready to encode remaining frames */
|
||||
|
|
@ -619,7 +636,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
|
|||
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
|
||||
dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
|
||||
dst_size = vb2_plane_size(dst_mb->b, 0);
|
||||
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
|
||||
dst_size);
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -638,14 +656,23 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
|
|||
list_del(&dst_mb->list);
|
||||
ctx->dst_queue_cnt--;
|
||||
vb2_set_plane_payload(dst_mb->b, 0,
|
||||
s5p_mfc_get_enc_strm_size());
|
||||
s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev));
|
||||
vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
}
|
||||
ctx->state = MFCINST_RUNNING;
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
if (IS_MFCV6(dev)) {
|
||||
ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
|
||||
} else {
|
||||
ctx->state = MFCINST_RUNNING;
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
}
|
||||
|
||||
if (IS_MFCV6(dev))
|
||||
ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops,
|
||||
get_enc_dpb_count, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -662,14 +689,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
|
|||
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
|
||||
src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
|
||||
src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
|
||||
s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr,
|
||||
src_c_addr);
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
|
||||
spin_lock_irqsave(&dev->irqlock, flags);
|
||||
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
|
||||
dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
|
||||
dst_size = vb2_plane_size(dst_mb->b, 0);
|
||||
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
|
||||
dst_size);
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
|
||||
return 0;
|
||||
|
|
@ -685,15 +714,16 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
|
|||
unsigned int strm_size;
|
||||
unsigned long flags;
|
||||
|
||||
slice_type = s5p_mfc_get_enc_slice_type();
|
||||
strm_size = s5p_mfc_get_enc_strm_size();
|
||||
slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
|
||||
strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
|
||||
mfc_debug(2, "Encoded slice type: %d", slice_type);
|
||||
mfc_debug(2, "Encoded stream size: %d", strm_size);
|
||||
mfc_debug(2, "Display order: %d",
|
||||
mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
|
||||
spin_lock_irqsave(&dev->irqlock, flags);
|
||||
if (slice_type >= 0) {
|
||||
s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
|
||||
&enc_y_addr, &enc_c_addr);
|
||||
list_for_each_entry(mb_entry, &ctx->src_queue, list) {
|
||||
mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
|
||||
mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
|
||||
|
|
@ -939,15 +969,16 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
pix_fmt_mp->plane_fmt[0].bytesperline = 0;
|
||||
ctx->dst_bufs_cnt = 0;
|
||||
ctx->capture_state = QUEUE_FREE;
|
||||
s5p_mfc_alloc_instance_buffer(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_clean_ctx_int_flags(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
if (s5p_mfc_wait_for_done_ctx(ctx, \
|
||||
S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
|
||||
S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) {
|
||||
/* Error or timeout */
|
||||
mfc_err("Error getting instance from hardware\n");
|
||||
s5p_mfc_release_instance_buffer(ctx);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer,
|
||||
ctx);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -958,6 +989,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
mfc_err("failed to set output format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!IS_MFCV6(dev) &&
|
||||
(fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
} else if (IS_MFCV6(dev) &&
|
||||
(fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
|
||||
mfc_err("Not supported format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fmt->num_planes != pix_fmt_mp->num_planes) {
|
||||
mfc_err("failed to set output format\n");
|
||||
ret = -EINVAL;
|
||||
|
|
@ -970,45 +1012,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
|||
mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
|
||||
pix_fmt_mp->width, pix_fmt_mp->height,
|
||||
ctx->img_width, ctx->img_height);
|
||||
if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
|
||||
ctx->buf_width = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12M_HALIGN);
|
||||
ctx->luma_size = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
|
||||
S5P_FIMV_NV12M_LVALIGN);
|
||||
ctx->chroma_size = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
|
||||
>> 1), S5P_FIMV_NV12M_CVALIGN);
|
||||
|
||||
ctx->luma_size = ALIGN(ctx->luma_size,
|
||||
S5P_FIMV_NV12M_SALIGN);
|
||||
ctx->chroma_size = ALIGN(ctx->chroma_size,
|
||||
S5P_FIMV_NV12M_SALIGN);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
|
||||
pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
|
||||
pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
|
||||
pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
|
||||
pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
|
||||
|
||||
pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
|
||||
pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
|
||||
pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
|
||||
pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
|
||||
|
||||
} else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
|
||||
ctx->buf_width = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12MT_HALIGN);
|
||||
ctx->luma_size = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
|
||||
S5P_FIMV_NV12MT_VALIGN);
|
||||
ctx->chroma_size = ALIGN(ctx->img_width,
|
||||
S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
|
||||
>> 1), S5P_FIMV_NV12MT_VALIGN);
|
||||
ctx->luma_size = ALIGN(ctx->luma_size,
|
||||
S5P_FIMV_NV12MT_SALIGN);
|
||||
ctx->chroma_size = ALIGN(ctx->chroma_size,
|
||||
S5P_FIMV_NV12MT_SALIGN);
|
||||
|
||||
pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
|
||||
pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
|
||||
pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
|
||||
pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
|
||||
}
|
||||
ctx->src_bufs_cnt = 0;
|
||||
ctx->output_state = QUEUE_FREE;
|
||||
} else {
|
||||
|
|
@ -1023,6 +1033,7 @@ out:
|
|||
static int vidioc_reqbufs(struct file *file, void *priv,
|
||||
struct v4l2_requestbuffers *reqbufs)
|
||||
{
|
||||
struct s5p_mfc_dev *dev = video_drvdata(file);
|
||||
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -1042,12 +1053,16 @@ static int vidioc_reqbufs(struct file *file, void *priv,
|
|||
return ret;
|
||||
}
|
||||
ctx->capture_state = QUEUE_BUFS_REQUESTED;
|
||||
ret = s5p_mfc_alloc_codec_buffers(ctx);
|
||||
if (ret) {
|
||||
mfc_err("Failed to allocate encoding buffers\n");
|
||||
reqbufs->count = 0;
|
||||
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
|
||||
return -ENOMEM;
|
||||
|
||||
if (!IS_MFCV6(dev)) {
|
||||
ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
|
||||
alloc_codec_buffers, ctx);
|
||||
if (ret) {
|
||||
mfc_err("Failed to allocate encoding buffers\n");
|
||||
reqbufs->count = 0;
|
||||
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
if (ctx->output_state != QUEUE_FREE) {
|
||||
|
|
@ -1310,6 +1325,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
p->codec.h264.profile =
|
||||
S5P_FIMV_ENC_PROFILE_H264_BASELINE;
|
||||
break;
|
||||
case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
|
||||
if (IS_MFCV6(dev))
|
||||
p->codec.h264.profile =
|
||||
S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
|
@ -1349,7 +1371,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
p->codec.h264._8x8_transform = ctrl->val;
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
|
||||
p->codec.h264.rc_mb = ctrl->val;
|
||||
p->rc_mb = ctrl->val;
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
|
||||
p->codec.h264.rc_frame_qp = ctrl->val;
|
||||
|
|
@ -1500,7 +1522,7 @@ int vidioc_encoder_cmd(struct file *file, void *priv,
|
|||
mfc_debug(2, "EOS: empty src queue, entering finishing state");
|
||||
ctx->state = MFCINST_FINISHING;
|
||||
spin_unlock_irqrestore(&dev->irqlock, flags);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
} else {
|
||||
mfc_debug(2, "EOS: marking last buffer of stream");
|
||||
buf = list_entry(ctx->src_queue.prev,
|
||||
|
|
@ -1583,6 +1605,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
|
|||
unsigned int psize[], void *allocators[])
|
||||
{
|
||||
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
|
||||
struct s5p_mfc_dev *dev = ctx->dev;
|
||||
|
||||
if (ctx->state != MFCINST_GOT_INST) {
|
||||
mfc_err("inavlid state: %d\n", ctx->state);
|
||||
|
|
@ -1611,8 +1634,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
|
|||
*buf_count = MFC_MAX_BUFFERS;
|
||||
psize[0] = ctx->luma_size;
|
||||
psize[1] = ctx->chroma_size;
|
||||
allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
|
||||
allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
|
||||
if (IS_MFCV6(dev)) {
|
||||
allocators[0] =
|
||||
ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
|
||||
allocators[1] =
|
||||
ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
|
||||
} else {
|
||||
allocators[0] =
|
||||
ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
|
||||
allocators[1] =
|
||||
ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
|
||||
}
|
||||
} else {
|
||||
mfc_err("inavlid queue type: %d\n", vq->type);
|
||||
return -EINVAL;
|
||||
|
|
@ -1715,7 +1747,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
|
|||
/* If context is ready then dev = work->data;schedule it to run */
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1729,19 +1761,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q)
|
|||
ctx->state == MFCINST_RUNNING) &&
|
||||
dev->curr_ctx == ctx->num && dev->hw_lock) {
|
||||
ctx->state = MFCINST_ABORT;
|
||||
s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET,
|
||||
s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
|
||||
0);
|
||||
}
|
||||
ctx->state = MFCINST_FINISHED;
|
||||
spin_lock_irqsave(&dev->irqlock, flags);
|
||||
if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
|
||||
s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
|
||||
&ctx->vq_dst);
|
||||
INIT_LIST_HEAD(&ctx->dst_queue);
|
||||
ctx->dst_queue_cnt = 0;
|
||||
}
|
||||
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
cleanup_ref_queue(ctx);
|
||||
s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
|
||||
&ctx->vq_src);
|
||||
INIT_LIST_HEAD(&ctx->src_queue);
|
||||
ctx->src_queue_cnt = 0;
|
||||
}
|
||||
|
|
@ -1782,7 +1816,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
|
|||
}
|
||||
if (s5p_mfc_ctx_ready(ctx))
|
||||
set_work_bit_irqsave(ctx);
|
||||
s5p_mfc_try_run(dev);
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
}
|
||||
|
||||
static struct vb2_ops s5p_mfc_enc_qops = {
|
||||
|
|
@ -1880,3 +1914,13 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
|
|||
for (i = 0; i < NUM_CTRLS; i++)
|
||||
ctx->ctrls[i] = NULL;
|
||||
}
|
||||
|
||||
void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
|
||||
{
|
||||
struct v4l2_format f;
|
||||
f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
|
||||
ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
|
||||
f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
|
||||
ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
|
|||
struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
|
||||
int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
#endif /* S5P_MFC_ENC_H_ */
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include "regs-mfc.h"
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_intr.h"
|
||||
|
|
@ -28,7 +27,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
|
|||
|
||||
ret = wait_event_interruptible_timeout(dev->queue,
|
||||
(dev->int_cond && (dev->int_type == command
|
||||
|| dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
|
||||
|| dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
|
||||
msecs_to_jiffies(MFC_INT_TIMEOUT));
|
||||
if (ret == 0) {
|
||||
mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
|
||||
|
|
@ -40,7 +39,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
|
|||
}
|
||||
mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
|
||||
dev->int_type, command);
|
||||
if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
|
||||
if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -60,12 +59,12 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
|
|||
if (interrupt) {
|
||||
ret = wait_event_interruptible_timeout(ctx->queue,
|
||||
(ctx->int_cond && (ctx->int_type == command
|
||||
|| ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
|
||||
|| ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
|
||||
msecs_to_jiffies(MFC_INT_TIMEOUT));
|
||||
} else {
|
||||
ret = wait_event_timeout(ctx->queue,
|
||||
(ctx->int_cond && (ctx->int_type == command
|
||||
|| ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)),
|
||||
|| ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
|
||||
msecs_to_jiffies(MFC_INT_TIMEOUT));
|
||||
}
|
||||
if (ret == 0) {
|
||||
|
|
@ -78,7 +77,7 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
|
|||
}
|
||||
mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
|
||||
ctx->int_type, command);
|
||||
if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)
|
||||
if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* drivers/media/platform/samsung/mfc5/s5p_mfc_opr.h
|
||||
* drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
|
||||
*
|
||||
* Header file for Samsung MFC (Multi Function Codec - FIMV) driver
|
||||
* Contains declarations of hw related functions.
|
||||
*
|
||||
* Kamil Debski, Copyright (C) 2011 Samsung Electronics
|
||||
* Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -17,77 +17,68 @@
|
|||
|
||||
#include "s5p_mfc_common.h"
|
||||
|
||||
int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
|
||||
int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
|
||||
struct s5p_mfc_hw_ops {
|
||||
int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
|
||||
void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
|
||||
int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
|
||||
void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
|
||||
int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
|
||||
void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
|
||||
int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
|
||||
void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
|
||||
void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
|
||||
void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
|
||||
int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx,
|
||||
int buf_addr, unsigned int start_num_byte,
|
||||
unsigned int buf_size);
|
||||
int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx);
|
||||
int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
|
||||
unsigned long addr, unsigned int size);
|
||||
void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
|
||||
unsigned long y_addr, unsigned long c_addr);
|
||||
void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
|
||||
unsigned long *y_addr, unsigned long *c_addr);
|
||||
int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx);
|
||||
int (*init_decode)(struct s5p_mfc_ctx *ctx);
|
||||
int (*init_encode)(struct s5p_mfc_ctx *ctx);
|
||||
int (*encode_one_frame)(struct s5p_mfc_ctx *ctx);
|
||||
void (*try_run)(struct s5p_mfc_dev *dev);
|
||||
void (*cleanup_queue)(struct list_head *lh,
|
||||
struct vb2_queue *vq);
|
||||
void (*clear_int_flags)(struct s5p_mfc_dev *dev);
|
||||
void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data,
|
||||
unsigned int ofs);
|
||||
unsigned int (*read_info)(struct s5p_mfc_ctx *ctx,
|
||||
unsigned int ofs);
|
||||
int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
|
||||
int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
|
||||
int (*get_dspl_status)(struct s5p_mfc_dev *dev);
|
||||
int (*get_dec_status)(struct s5p_mfc_dev *dev);
|
||||
int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
|
||||
int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
|
||||
int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
|
||||
int (*get_int_reason)(struct s5p_mfc_dev *dev);
|
||||
int (*get_int_err)(struct s5p_mfc_dev *dev);
|
||||
int (*err_dec)(unsigned int err);
|
||||
int (*err_dspl)(unsigned int err);
|
||||
int (*get_img_width)(struct s5p_mfc_dev *dev);
|
||||
int (*get_img_height)(struct s5p_mfc_dev *dev);
|
||||
int (*get_dpb_count)(struct s5p_mfc_dev *dev);
|
||||
int (*get_mv_count)(struct s5p_mfc_dev *dev);
|
||||
int (*get_inst_no)(struct s5p_mfc_dev *dev);
|
||||
int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
|
||||
int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
|
||||
int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
|
||||
int (*get_enc_pic_count)(struct s5p_mfc_dev *dev);
|
||||
int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx);
|
||||
int (*get_mvc_num_views)(struct s5p_mfc_dev *dev);
|
||||
int (*get_mvc_view_id)(struct s5p_mfc_dev *dev);
|
||||
unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
|
||||
unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
|
||||
unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
|
||||
unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
|
||||
};
|
||||
|
||||
/* Decoding functions */
|
||||
int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
|
||||
int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
|
||||
unsigned int start_num_byte,
|
||||
unsigned int buf_size);
|
||||
|
||||
/* Encoding functions */
|
||||
void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
|
||||
unsigned long y_addr, unsigned long c_addr);
|
||||
int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
|
||||
unsigned long addr, unsigned int size);
|
||||
void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
|
||||
unsigned long *y_addr, unsigned long *c_addr);
|
||||
int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
|
||||
|
||||
int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
|
||||
enum s5p_mfc_decode_arg last_frame);
|
||||
int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
|
||||
|
||||
/* Memory allocation */
|
||||
int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
|
||||
void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
|
||||
void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
|
||||
|
||||
#define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_DISPLAY_Y_ADR) << \
|
||||
MFC_OFFSET_SHIFT)
|
||||
#define s5p_mfc_get_dec_y_adr() (readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_DECODE_Y_ADR) << \
|
||||
MFC_OFFSET_SHIFT)
|
||||
#define s5p_mfc_get_dspl_status() readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_DISPLAY_STATUS)
|
||||
#define s5p_mfc_get_dec_status() readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_DECODE_STATUS)
|
||||
#define s5p_mfc_get_frame_type() (readl(dev->regs_base + \
|
||||
S5P_FIMV_DECODE_FRAME_TYPE) \
|
||||
& S5P_FIMV_DECODE_FRAME_MASK)
|
||||
#define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_CONSUMED_BYTES)
|
||||
#define s5p_mfc_get_int_reason() (readl(dev->regs_base + \
|
||||
S5P_FIMV_RISC2HOST_CMD) & \
|
||||
S5P_FIMV_RISC2HOST_CMD_MASK)
|
||||
#define s5p_mfc_get_int_err() readl(dev->regs_base + \
|
||||
S5P_FIMV_RISC2HOST_ARG2)
|
||||
#define s5p_mfc_err_dec(x) (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
|
||||
S5P_FIMV_ERR_DEC_SHIFT)
|
||||
#define s5p_mfc_err_dspl(x) (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
|
||||
S5P_FIMV_ERR_DSPL_SHIFT)
|
||||
#define s5p_mfc_get_img_width() readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_HRESOL)
|
||||
#define s5p_mfc_get_img_height() readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_VRESOL)
|
||||
#define s5p_mfc_get_dpb_count() readl(dev->regs_base + \
|
||||
S5P_FIMV_SI_BUF_NUMBER)
|
||||
#define s5p_mfc_get_inst_no() readl(dev->regs_base + \
|
||||
S5P_FIMV_RISC2HOST_ARG1)
|
||||
#define s5p_mfc_get_enc_strm_size() readl(dev->regs_base + \
|
||||
S5P_FIMV_ENC_SI_STRM_SIZE)
|
||||
#define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \
|
||||
S5P_FIMV_ENC_SI_SLICE_TYPE)
|
||||
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
|
||||
|
||||
#endif /* S5P_MFC_OPR_H_ */
|
||||
|
|
|
|||
1794
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
Normal file
1794
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,17 +1,22 @@
|
|||
/*
|
||||
* linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
|
||||
* drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.h
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
* Header file for Samsung MFC (Multi Function Codec - FIMV) driver
|
||||
* Contains declarations of hw related functions.
|
||||
*
|
||||
* Kamil Debski, Copyright (C) 2011 Samsung Electronics
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef S5P_MFC_SHM_H_
|
||||
#define S5P_MFC_SHM_H_
|
||||
#ifndef S5P_MFC_OPR_V5_H_
|
||||
#define S5P_MFC_OPR_V5_H_
|
||||
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
|
||||
enum MFC_SHM_OFS {
|
||||
EXTENEDED_DECODE_STATUS = 0x00, /* D */
|
||||
|
|
@ -71,20 +76,10 @@ enum MFC_SHM_OFS {
|
|||
DBG_HISTORY_INPUT1 = 0xD4, /* C */
|
||||
DBG_HISTORY_OUTPUT = 0xD8, /* C */
|
||||
HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */
|
||||
FRAME_PACK_SEI_ENABLE = 0x168, /* C */
|
||||
FRAME_PACK_SEI_AVAIL = 0x16c, /* D */
|
||||
FRAME_PACK_SEI_INFO = 0x17c, /* E */
|
||||
};
|
||||
|
||||
int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
|
||||
|
||||
#define s5p_mfc_write_shm(ctx, x, ofs) \
|
||||
do { \
|
||||
writel(x, (ctx->shm + ofs)); \
|
||||
wmb(); \
|
||||
} while (0)
|
||||
|
||||
static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
|
||||
{
|
||||
rmb();
|
||||
return readl(ctx->shm + ofs);
|
||||
}
|
||||
|
||||
#endif /* S5P_MFC_SHM_H_ */
|
||||
struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
|
||||
#endif /* S5P_MFC_OPR_H_ */
|
||||
1956
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
Normal file
1956
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
Normal file
File diff suppressed because it is too large
Load diff
50
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
Normal file
50
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
|
||||
*
|
||||
* Header file for Samsung MFC (Multi Function Codec - FIMV) driver
|
||||
* Contains declarations of hw related functions.
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef S5P_MFC_OPR_V6_H_
|
||||
#define S5P_MFC_OPR_V6_H_
|
||||
|
||||
#include "s5p_mfc_common.h"
|
||||
#include "s5p_mfc_opr.h"
|
||||
|
||||
#define MFC_CTRL_MODE_CUSTOM MFC_CTRL_MODE_SFR
|
||||
|
||||
#define MB_WIDTH(x_size) DIV_ROUND_UP(x_size, 16)
|
||||
#define MB_HEIGHT(y_size) DIV_ROUND_UP(y_size, 16)
|
||||
#define S5P_MFC_DEC_MV_SIZE_V6(x, y) (MB_WIDTH(x) * \
|
||||
(((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
|
||||
|
||||
/* Definition */
|
||||
#define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1)
|
||||
#define ENC_MULTI_SLICE_BIT_MIN 2800
|
||||
#define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1)
|
||||
#define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1)
|
||||
#define ENC_H264_LOOP_FILTER_AB_MIN -12
|
||||
#define ENC_H264_LOOP_FILTER_AB_MAX 12
|
||||
#define ENC_H264_RC_FRAME_RATE_MAX ((1 << 16) - 1)
|
||||
#define ENC_H263_RC_FRAME_RATE_MAX ((1 << 16) - 1)
|
||||
#define ENC_H264_PROFILE_MAX 3
|
||||
#define ENC_H264_LEVEL_MAX 42
|
||||
#define ENC_MPEG4_VOP_TIME_RES_MAX ((1 << 16) - 1)
|
||||
#define FRAME_DELTA_H264_H263 1
|
||||
#define TIGHT_CBR_MAX 10
|
||||
|
||||
/* Definitions for shared memory compatibility */
|
||||
#define PIC_TIME_TOP_V6 S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6
|
||||
#define PIC_TIME_BOT_V6 S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6
|
||||
#define CROP_INFO_H_V6 S5P_FIMV_D_DISPLAY_CROP_INFO1_V6
|
||||
#define CROP_INFO_V_V6 S5P_FIMV_D_DISPLAY_CROP_INFO2_V6
|
||||
|
||||
struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
|
||||
#endif /* S5P_MFC_OPR_V6_H_ */
|
||||
|
|
@ -20,7 +20,6 @@
|
|||
#include "s5p_mfc_debug.h"
|
||||
#include "s5p_mfc_pm.h"
|
||||
|
||||
#define MFC_CLKNAME "sclk_mfc"
|
||||
#define MFC_GATE_CLK_NAME "mfc"
|
||||
|
||||
#define CLK_DEBUG
|
||||
|
|
@ -51,7 +50,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
|
|||
goto err_p_ip_clk;
|
||||
}
|
||||
|
||||
pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME);
|
||||
pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name);
|
||||
if (IS_ERR(pm->clock)) {
|
||||
mfc_err("Failed to get MFC clock\n");
|
||||
ret = PTR_ERR(pm->clock);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue