diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-11 14:07:19 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-11 14:07:19 -0400 |
commit | bf3b202b41999f88f091632f13842b7234bd58b7 (patch) | |
tree | e2861fcca522cc299e6106fa6c78d85a4a6eedeb /drivers/media | |
parent | 782cd9ee985b1523f1ddad57657a24d7855d9e4d (diff) | |
parent | 1fdead8ad31d3aa833bc37739273fcde89ace93c (diff) |
Merge branch 'staging/for_v3.7' into v4l_for_linus
Applied on the top of changeset 782cd9e, as some of those patches
depend on some fixes that went via -arm tree.
* staging/for_v3.7: (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
...
Diffstat (limited to 'drivers/media')
136 files changed, 7026 insertions, 3086 deletions
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 8f58f241c10d..7e92793260f0 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c | |||
@@ -966,6 +966,8 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | |||
966 | break; | 966 | break; |
967 | } | 967 | } |
968 | 968 | ||
969 | c->lna = LNA_AUTO; | ||
970 | |||
969 | return 0; | 971 | return 0; |
970 | } | 972 | } |
971 | 973 | ||
@@ -1054,6 +1056,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { | |||
1054 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0), | 1056 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0), |
1055 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0), | 1057 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0), |
1056 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0), | 1058 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0), |
1059 | |||
1060 | _DTV_CMD(DTV_LNA, 0, 0), | ||
1057 | }; | 1061 | }; |
1058 | 1062 | ||
1059 | static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) | 1063 | 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, | |||
1440 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d; | 1444 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d; |
1441 | break; | 1445 | break; |
1442 | 1446 | ||
1447 | case DTV_LNA: | ||
1448 | tvp->u.data = c->lna; | ||
1449 | break; | ||
1450 | |||
1443 | default: | 1451 | default: |
1444 | return -EINVAL; | 1452 | return -EINVAL; |
1445 | } | 1453 | } |
@@ -1731,10 +1739,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1731 | case DTV_INTERLEAVING: | 1739 | case DTV_INTERLEAVING: |
1732 | c->interleaving = tvp->u.data; | 1740 | c->interleaving = tvp->u.data; |
1733 | break; | 1741 | break; |
1734 | case DTV_LNA: | ||
1735 | if (fe->ops.set_lna) | ||
1736 | r = fe->ops.set_lna(fe, tvp->u.data); | ||
1737 | break; | ||
1738 | 1742 | ||
1739 | /* ISDB-T Support here */ | 1743 | /* ISDB-T Support here */ |
1740 | case DTV_ISDBT_PARTIAL_RECEPTION: | 1744 | case DTV_ISDBT_PARTIAL_RECEPTION: |
@@ -1806,6 +1810,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1806 | fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data; | 1810 | fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data; |
1807 | break; | 1811 | break; |
1808 | 1812 | ||
1813 | case DTV_LNA: | ||
1814 | c->lna = tvp->u.data; | ||
1815 | if (fe->ops.set_lna) | ||
1816 | r = fe->ops.set_lna(fe); | ||
1817 | break; | ||
1818 | |||
1809 | default: | 1819 | default: |
1810 | return -EINVAL; | 1820 | return -EINVAL; |
1811 | } | 1821 | } |
@@ -2309,7 +2319,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
2309 | fepriv->tune_mode_flags = (unsigned long) parg; | 2319 | fepriv->tune_mode_flags = (unsigned long) parg; |
2310 | err = 0; | 2320 | err = 0; |
2311 | break; | 2321 | break; |
2312 | }; | 2322 | } |
2313 | 2323 | ||
2314 | return err; | 2324 | return err; |
2315 | } | 2325 | } |
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 44a445cee74f..97112cd88a17 100644 --- a/drivers/media/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h | |||
@@ -303,7 +303,7 @@ struct dvb_frontend_ops { | |||
303 | int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); | 303 | int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); |
304 | int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); | 304 | int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); |
305 | int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); | 305 | int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); |
306 | int (*set_lna)(struct dvb_frontend *, int); | 306 | int (*set_lna)(struct dvb_frontend *); |
307 | 307 | ||
308 | /* These callbacks are for devices that implement their own | 308 | /* These callbacks are for devices that implement their own |
309 | * tuning algorithms, rather than a simple swzigzag | 309 | * tuning algorithms, rather than a simple swzigzag |
@@ -391,6 +391,8 @@ struct dtv_frontend_properties { | |||
391 | u8 atscmh_sccc_code_mode_b; | 391 | u8 atscmh_sccc_code_mode_b; |
392 | u8 atscmh_sccc_code_mode_c; | 392 | u8 atscmh_sccc_code_mode_c; |
393 | u8 atscmh_sccc_code_mode_d; | 393 | u8 atscmh_sccc_code_mode_d; |
394 | |||
395 | u32 lna; | ||
394 | }; | 396 | }; |
395 | 397 | ||
396 | struct dvb_frontend { | 398 | struct dvb_frontend { |
diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c index cff44a389b40..74fbb5d58bed 100644 --- a/drivers/media/dvb-frontends/a8293.c +++ b/drivers/media/dvb-frontends/a8293.c | |||
@@ -90,7 +90,7 @@ static int a8293_set_voltage(struct dvb_frontend *fe, | |||
90 | default: | 90 | default: |
91 | ret = -EINVAL; | 91 | ret = -EINVAL; |
92 | goto err; | 92 | goto err; |
93 | }; | 93 | } |
94 | 94 | ||
95 | ret = a8293_wr(priv, &priv->reg[0], 1); | 95 | ret = a8293_wr(priv, &priv->reg[0], 1); |
96 | if (ret) | 96 | if (ret) |
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index e9f04a36577b..a204f2828820 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c | |||
@@ -241,7 +241,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) | |||
241 | KBUILD_MODNAME, gpio); | 241 | KBUILD_MODNAME, gpio); |
242 | ret = -EINVAL; | 242 | ret = -EINVAL; |
243 | goto err; | 243 | goto err; |
244 | }; | 244 | } |
245 | 245 | ||
246 | switch (gpio) { | 246 | switch (gpio) { |
247 | case 0: | 247 | case 0: |
@@ -253,7 +253,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) | |||
253 | default: | 253 | default: |
254 | pos = 4; | 254 | pos = 4; |
255 | break; | 255 | break; |
256 | }; | 256 | } |
257 | 257 | ||
258 | ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval); | 258 | ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval); |
259 | if (ret) | 259 | if (ret) |
@@ -726,7 +726,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | |||
726 | default: | 726 | default: |
727 | dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__); | 727 | dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__); |
728 | auto_mode = 1; | 728 | auto_mode = 1; |
729 | }; | 729 | } |
730 | 730 | ||
731 | switch (c->modulation) { | 731 | switch (c->modulation) { |
732 | case QAM_AUTO: | 732 | case QAM_AUTO: |
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 8162d939c4b2..464ad878490b 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c | |||
@@ -408,7 +408,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe) | |||
408 | { | 408 | { |
409 | struct af9033_state *state = fe->demodulator_priv; | 409 | struct af9033_state *state = fe->demodulator_priv; |
410 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 410 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
411 | int ret, i, spec_inv; | 411 | int ret, i, spec_inv, sampling_freq; |
412 | u8 tmp, buf[3], bandwidth_reg_val; | 412 | u8 tmp, buf[3], bandwidth_reg_val; |
413 | u32 if_frequency, freq_cw, adc_freq; | 413 | u32 if_frequency, freq_cw, adc_freq; |
414 | 414 | ||
@@ -465,18 +465,20 @@ static int af9033_set_frontend(struct dvb_frontend *fe) | |||
465 | else | 465 | else |
466 | if_frequency = 0; | 466 | if_frequency = 0; |
467 | 467 | ||
468 | while (if_frequency > (adc_freq / 2)) | 468 | sampling_freq = if_frequency; |
469 | if_frequency -= adc_freq; | ||
470 | 469 | ||
471 | if (if_frequency >= 0) | 470 | while (sampling_freq > (adc_freq / 2)) |
471 | sampling_freq -= adc_freq; | ||
472 | |||
473 | if (sampling_freq >= 0) | ||
472 | spec_inv *= -1; | 474 | spec_inv *= -1; |
473 | else | 475 | else |
474 | if_frequency *= -1; | 476 | sampling_freq *= -1; |
475 | 477 | ||
476 | freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul); | 478 | freq_cw = af9033_div(state, sampling_freq, adc_freq, 23ul); |
477 | 479 | ||
478 | if (spec_inv == -1) | 480 | if (spec_inv == -1) |
479 | freq_cw *= -1; | 481 | freq_cw = 0x800000 - freq_cw; |
480 | 482 | ||
481 | /* get adc multiplies */ | 483 | /* get adc multiplies */ |
482 | ret = af9033_rd_reg(state, 0x800045, &tmp); | 484 | ret = af9033_rd_reg(state, 0x800045, &tmp); |
diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c index 033cd7ad3ca2..1b77909c0c71 100644 --- a/drivers/media/dvb-frontends/bcm3510.c +++ b/drivers/media/dvb-frontends/bcm3510.c | |||
@@ -527,7 +527,7 @@ static int bcm3510_set_frontend(struct dvb_frontend *fe) | |||
527 | cmd.ACQUIRE1.IF_FREQ = 0x0; | 527 | cmd.ACQUIRE1.IF_FREQ = 0x0; |
528 | default: | 528 | default: |
529 | return -EINVAL; | 529 | return -EINVAL; |
530 | }; | 530 | } |
531 | cmd.ACQUIRE0.OFFSET = 0; | 531 | cmd.ACQUIRE0.OFFSET = 0; |
532 | cmd.ACQUIRE0.NTSCSWEEP = 1; | 532 | cmd.ACQUIRE0.NTSCSWEEP = 1; |
533 | cmd.ACQUIRE0.FA = 1; | 533 | cmd.ACQUIRE0.FA = 1; |
diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c index 3180f5b2a6a6..0cd6927e654c 100644 --- a/drivers/media/dvb-frontends/cx24110.c +++ b/drivers/media/dvb-frontends/cx24110.c | |||
@@ -218,7 +218,7 @@ static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec) | |||
218 | } else | 218 | } else |
219 | return -EOPNOTSUPP; | 219 | return -EOPNOTSUPP; |
220 | /* fixme (low): which is the correct return code? */ | 220 | /* fixme (low): which is the correct return code? */ |
221 | }; | 221 | } |
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |
224 | 224 | ||
@@ -275,7 +275,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) | |||
275 | cx24110_writereg(state,0x07,tmp|0x3); | 275 | cx24110_writereg(state,0x07,tmp|0x3); |
276 | cx24110_writereg(state,0x06,0x78); | 276 | cx24110_writereg(state,0x06,0x78); |
277 | fclk=90999000UL; | 277 | fclk=90999000UL; |
278 | }; | 278 | } |
279 | dprintk("cx24110 debug: fclk %d Hz\n",fclk); | 279 | dprintk("cx24110 debug: fclk %d Hz\n",fclk); |
280 | /* we need to divide two integers with approx. 27 bits in 32 bit | 280 | /* we need to divide two integers with approx. 27 bits in 32 bit |
281 | arithmetic giving a 25 bit result */ | 281 | arithmetic giving a 25 bit result */ |
@@ -362,7 +362,7 @@ static int cx24110_initfe(struct dvb_frontend* fe) | |||
362 | 362 | ||
363 | for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) { | 363 | for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) { |
364 | cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); | 364 | cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); |
365 | }; | 365 | } |
366 | 366 | ||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 42648643693e..9b658c1cf39a 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c | |||
@@ -688,7 +688,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, | |||
688 | { | 688 | { |
689 | struct cxd2820r_priv *priv; | 689 | struct cxd2820r_priv *priv; |
690 | int ret; | 690 | int ret; |
691 | u8 tmp, gpio[GPIO_COUNT]; | 691 | u8 tmp; |
692 | 692 | ||
693 | priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL); | 693 | priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL); |
694 | if (!priv) { | 694 | if (!priv) { |
@@ -735,6 +735,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, | |||
735 | * Use static GPIO configuration if GPIOLIB is undefined. | 735 | * Use static GPIO configuration if GPIOLIB is undefined. |
736 | * This is fallback condition. | 736 | * This is fallback condition. |
737 | */ | 737 | */ |
738 | u8 gpio[GPIO_COUNT]; | ||
738 | gpio[0] = (*gpio_chip_base >> 0) & 0x07; | 739 | gpio[0] = (*gpio_chip_base >> 0) & 0x07; |
739 | gpio[1] = (*gpio_chip_base >> 3) & 0x07; | 740 | gpio[1] = (*gpio_chip_base >> 3) & 0x07; |
740 | gpio[2] = 0; | 741 | gpio[2] = 0; |
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index f380eb43e9d5..6d9853750d2b 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c | |||
@@ -991,7 +991,7 @@ static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult) | |||
991 | if (nrRetries > DRXD_MAX_RETRIES) { | 991 | if (nrRetries > DRXD_MAX_RETRIES) { |
992 | status = -1; | 992 | status = -1; |
993 | break; | 993 | break; |
994 | }; | 994 | } |
995 | status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0); | 995 | status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0); |
996 | } while (waitCmd != 0); | 996 | } while (waitCmd != 0); |
997 | 997 | ||
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c index 4c8ac2657c4a..5b639087ce45 100644 --- a/drivers/media/dvb-frontends/ds3000.c +++ b/drivers/media/dvb-frontends/ds3000.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "ds3000.h" | 30 | #include "ds3000.h" |
31 | 31 | ||
32 | static int debug; | 32 | static int debug; |
33 | static int force_fw_upload; | ||
33 | 34 | ||
34 | #define dprintk(args...) \ | 35 | #define dprintk(args...) \ |
35 | do { \ | 36 | do { \ |
@@ -392,11 +393,13 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe) | |||
392 | 393 | ||
393 | dprintk("%s()\n", __func__); | 394 | dprintk("%s()\n", __func__); |
394 | 395 | ||
395 | if (ds3000_readreg(state, 0xb2) <= 0) | 396 | ret = ds3000_readreg(state, 0xb2); |
397 | if (ret < 0) | ||
396 | return ret; | 398 | return ret; |
397 | 399 | ||
398 | if (state->skip_fw_load) | 400 | if (state->skip_fw_load || !force_fw_upload) |
399 | return 0; | 401 | return 0; /* Firmware already uploaded, skipping */ |
402 | |||
400 | /* Load firmware */ | 403 | /* Load firmware */ |
401 | /* request the firmware, this will block until someone uploads it */ | 404 | /* request the firmware, this will block until someone uploads it */ |
402 | printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, | 405 | printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, |
@@ -1306,6 +1309,9 @@ static struct dvb_frontend_ops ds3000_ops = { | |||
1306 | module_param(debug, int, 0644); | 1309 | module_param(debug, int, 0644); |
1307 | MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); | 1310 | MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); |
1308 | 1311 | ||
1312 | module_param(force_fw_upload, int, 0644); | ||
1313 | MODULE_PARM_DESC(force_fw_upload, "Force firmware upload (default:0)"); | ||
1314 | |||
1309 | MODULE_DESCRIPTION("DVB Frontend module for Montage Technology " | 1315 | MODULE_DESCRIPTION("DVB Frontend module for Montage Technology " |
1310 | "DS3000/TS2020 hardware"); | 1316 | "DS3000/TS2020 hardware"); |
1311 | MODULE_AUTHOR("Konstantin Dimitrov"); | 1317 | MODULE_AUTHOR("Konstantin Dimitrov"); |
diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c index dcfc902c8678..d5acc304786b 100644 --- a/drivers/media/dvb-frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c | |||
@@ -121,16 +121,13 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void) | |||
121 | 121 | ||
122 | /* allocate memory for the internal state */ | 122 | /* allocate memory for the internal state */ |
123 | state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); | 123 | state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); |
124 | if (state == NULL) goto error; | 124 | if (!state) |
125 | return NULL; | ||
125 | 126 | ||
126 | /* create dvb_frontend */ | 127 | /* create dvb_frontend */ |
127 | memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops)); | 128 | memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops)); |
128 | state->frontend.demodulator_priv = state; | 129 | state->frontend.demodulator_priv = state; |
129 | return &state->frontend; | 130 | return &state->frontend; |
130 | |||
131 | error: | ||
132 | kfree(state); | ||
133 | return NULL; | ||
134 | } | 131 | } |
135 | 132 | ||
136 | static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; | 133 | static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; |
@@ -141,16 +138,13 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) | |||
141 | 138 | ||
142 | /* allocate memory for the internal state */ | 139 | /* allocate memory for the internal state */ |
143 | state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); | 140 | state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); |
144 | if (state == NULL) goto error; | 141 | if (!state) |
142 | return NULL; | ||
145 | 143 | ||
146 | /* create dvb_frontend */ | 144 | /* create dvb_frontend */ |
147 | memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops)); | 145 | memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops)); |
148 | state->frontend.demodulator_priv = state; | 146 | state->frontend.demodulator_priv = state; |
149 | return &state->frontend; | 147 | return &state->frontend; |
150 | |||
151 | error: | ||
152 | kfree(state); | ||
153 | return NULL; | ||
154 | } | 148 | } |
155 | 149 | ||
156 | static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; | 150 | static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; |
@@ -161,16 +155,13 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void) | |||
161 | 155 | ||
162 | /* allocate memory for the internal state */ | 156 | /* allocate memory for the internal state */ |
163 | state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); | 157 | state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); |
164 | if (state == NULL) goto error; | 158 | if (!state) |
159 | return NULL; | ||
165 | 160 | ||
166 | /* create dvb_frontend */ | 161 | /* create dvb_frontend */ |
167 | memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops)); | 162 | memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops)); |
168 | state->frontend.demodulator_priv = state; | 163 | state->frontend.demodulator_priv = state; |
169 | return &state->frontend; | 164 | return &state->frontend; |
170 | |||
171 | error: | ||
172 | kfree(state); | ||
173 | return NULL; | ||
174 | } | 165 | } |
175 | 166 | ||
176 | static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { | 167 | static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { |
diff --git a/drivers/media/dvb-frontends/isl6405.c b/drivers/media/dvb-frontends/isl6405.c index 33d33f4d8867..0c642a5bf823 100644 --- a/drivers/media/dvb-frontends/isl6405.c +++ b/drivers/media/dvb-frontends/isl6405.c | |||
@@ -77,7 +77,7 @@ static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage | |||
77 | break; | 77 | break; |
78 | default: | 78 | default: |
79 | return -EINVAL; | 79 | return -EINVAL; |
80 | }; | 80 | } |
81 | } | 81 | } |
82 | isl6405->config |= isl6405->override_or; | 82 | isl6405->config |= isl6405->override_or; |
83 | isl6405->config &= isl6405->override_and; | 83 | isl6405->config &= isl6405->override_and; |
diff --git a/drivers/media/dvb-frontends/isl6421.c b/drivers/media/dvb-frontends/isl6421.c index 684c8ec166cb..0cb3f0f74c9c 100644 --- a/drivers/media/dvb-frontends/isl6421.c +++ b/drivers/media/dvb-frontends/isl6421.c | |||
@@ -63,7 +63,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage | |||
63 | break; | 63 | break; |
64 | default: | 64 | default: |
65 | return -EINVAL; | 65 | return -EINVAL; |
66 | }; | 66 | } |
67 | 67 | ||
68 | isl6421->config |= isl6421->override_or; | 68 | isl6421->config |= isl6421->override_or; |
69 | isl6421->config &= isl6421->override_and; | 69 | isl6421->config &= isl6421->override_and; |
diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c index 316457584fe7..c1c3400b2173 100644 --- a/drivers/media/dvb-frontends/itd1000.c +++ b/drivers/media/dvb-frontends/itd1000.c | |||
@@ -231,7 +231,7 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz) | |||
231 | state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF; | 231 | state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF; |
232 | itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln); | 232 | itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln); |
233 | 233 | ||
234 | itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */; | 234 | itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */ |
235 | itd1000_write_reg(state, PLLNL, plln & 0xff); | 235 | itd1000_write_reg(state, PLLNL, plln & 0xff); |
236 | itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f)); | 236 | itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f)); |
237 | itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff); | 237 | itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff); |
diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index cc11260e99df..5fd14f840ab0 100644 --- a/drivers/media/dvb-frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c | |||
@@ -1421,8 +1421,8 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config, | |||
1421 | config ? config->i2c_addr : 0); | 1421 | config ? config->i2c_addr : 0); |
1422 | 1422 | ||
1423 | state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL); | 1423 | state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL); |
1424 | if (state == NULL) | 1424 | if (!state) |
1425 | goto fail; | 1425 | return NULL; |
1426 | 1426 | ||
1427 | state->cfg = config; | 1427 | state->cfg = config; |
1428 | state->i2c_adap = i2c_adap; | 1428 | state->i2c_adap = i2c_adap; |
@@ -1449,10 +1449,6 @@ struct dvb_frontend *lg2160_attach(const struct lg2160_config *config, | |||
1449 | state->frontend.dtv_property_cache.atscmh_parade_id = 1; | 1449 | state->frontend.dtv_property_cache.atscmh_parade_id = 1; |
1450 | 1450 | ||
1451 | return &state->frontend; | 1451 | return &state->frontend; |
1452 | fail: | ||
1453 | lg_warn("unable to detect LG216x hardware\n"); | ||
1454 | kfree(state); | ||
1455 | return NULL; | ||
1456 | } | 1452 | } |
1457 | EXPORT_SYMBOL(lg2160_attach); | 1453 | EXPORT_SYMBOL(lg2160_attach); |
1458 | 1454 | ||
diff --git a/drivers/media/dvb-frontends/lnbp21.c b/drivers/media/dvb-frontends/lnbp21.c index 13437259eeac..f3ba7b5faa2e 100644 --- a/drivers/media/dvb-frontends/lnbp21.c +++ b/drivers/media/dvb-frontends/lnbp21.c | |||
@@ -65,7 +65,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, | |||
65 | break; | 65 | break; |
66 | default: | 66 | default: |
67 | return -EINVAL; | 67 | return -EINVAL; |
68 | }; | 68 | } |
69 | 69 | ||
70 | lnbp21->config |= lnbp21->override_or; | 70 | lnbp21->config |= lnbp21->override_or; |
71 | lnbp21->config &= lnbp21->override_and; | 71 | lnbp21->config &= lnbp21->override_and; |
@@ -108,7 +108,7 @@ static int lnbp21_set_tone(struct dvb_frontend *fe, | |||
108 | break; | 108 | break; |
109 | default: | 109 | default: |
110 | return -EINVAL; | 110 | return -EINVAL; |
111 | }; | 111 | } |
112 | 112 | ||
113 | lnbp21->config |= lnbp21->override_or; | 113 | lnbp21->config |= lnbp21->override_or; |
114 | lnbp21->config &= lnbp21->override_and; | 114 | lnbp21->config &= lnbp21->override_and; |
diff --git a/drivers/media/dvb-frontends/lnbp22.c b/drivers/media/dvb-frontends/lnbp22.c index 84ad0390a4a1..c463da7f6dcc 100644 --- a/drivers/media/dvb-frontends/lnbp22.c +++ b/drivers/media/dvb-frontends/lnbp22.c | |||
@@ -73,7 +73,7 @@ static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | |||
73 | break; | 73 | break; |
74 | default: | 74 | default: |
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | }; | 76 | } |
77 | 77 | ||
78 | dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]); | 78 | dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]); |
79 | return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO; | 79 | return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO; |
diff --git a/drivers/media/dvb-frontends/s5h1432.c b/drivers/media/dvb-frontends/s5h1432.c index 8352ce1c9556..6ec16a243741 100644 --- a/drivers/media/dvb-frontends/s5h1432.c +++ b/drivers/media/dvb-frontends/s5h1432.c | |||
@@ -351,8 +351,8 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config, | |||
351 | printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n"); | 351 | printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n"); |
352 | /* allocate memory for the internal state */ | 352 | /* allocate memory for the internal state */ |
353 | state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL); | 353 | state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL); |
354 | if (state == NULL) | 354 | if (!state) |
355 | goto error; | 355 | return NULL; |
356 | 356 | ||
357 | /* setup the state */ | 357 | /* setup the state */ |
358 | state->config = config; | 358 | state->config = config; |
@@ -367,10 +367,6 @@ struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config, | |||
367 | state->frontend.demodulator_priv = state; | 367 | state->frontend.demodulator_priv = state; |
368 | 368 | ||
369 | return &state->frontend; | 369 | return &state->frontend; |
370 | |||
371 | error: | ||
372 | kfree(state); | ||
373 | return NULL; | ||
374 | } | 370 | } |
375 | EXPORT_SYMBOL(s5h1432_attach); | 371 | EXPORT_SYMBOL(s5h1432_attach); |
376 | 372 | ||
diff --git a/drivers/media/dvb-frontends/s921.c b/drivers/media/dvb-frontends/s921.c index cd2288c07147..a271ac3eaec0 100644 --- a/drivers/media/dvb-frontends/s921.c +++ b/drivers/media/dvb-frontends/s921.c | |||
@@ -487,9 +487,9 @@ struct dvb_frontend *s921_attach(const struct s921_config *config, | |||
487 | kzalloc(sizeof(struct s921_state), GFP_KERNEL); | 487 | kzalloc(sizeof(struct s921_state), GFP_KERNEL); |
488 | 488 | ||
489 | dprintk("\n"); | 489 | dprintk("\n"); |
490 | if (state == NULL) { | 490 | if (!state) { |
491 | rc("Unable to kzalloc\n"); | 491 | rc("Unable to kzalloc\n"); |
492 | goto rcor; | 492 | return NULL; |
493 | } | 493 | } |
494 | 494 | ||
495 | /* setup the state */ | 495 | /* setup the state */ |
@@ -502,11 +502,6 @@ struct dvb_frontend *s921_attach(const struct s921_config *config, | |||
502 | state->frontend.demodulator_priv = state; | 502 | state->frontend.demodulator_priv = state; |
503 | 503 | ||
504 | return &state->frontend; | 504 | return &state->frontend; |
505 | |||
506 | rcor: | ||
507 | kfree(state); | ||
508 | |||
509 | return NULL; | ||
510 | } | 505 | } |
511 | EXPORT_SYMBOL(s921_attach); | 506 | EXPORT_SYMBOL(s921_attach); |
512 | 507 | ||
diff --git a/drivers/media/dvb-frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c index a68a64800df7..73b47cc6a13b 100644 --- a/drivers/media/dvb-frontends/si21xx.c +++ b/drivers/media/dvb-frontends/si21xx.c | |||
@@ -343,7 +343,7 @@ static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout) | |||
343 | return -ETIMEDOUT; | 343 | return -ETIMEDOUT; |
344 | } | 344 | } |
345 | msleep(10); | 345 | msleep(10); |
346 | }; | 346 | } |
347 | 347 | ||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
@@ -472,7 +472,7 @@ static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) | |||
472 | break; | 472 | break; |
473 | default: | 473 | default: |
474 | return -EINVAL; | 474 | return -EINVAL; |
475 | }; | 475 | } |
476 | } | 476 | } |
477 | 477 | ||
478 | static int si21xx_init(struct dvb_frontend *fe) | 478 | static int si21xx_init(struct dvb_frontend *fe) |
diff --git a/drivers/media/dvb-frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c index e37274c8f14e..2aa8ef76eba2 100644 --- a/drivers/media/dvb-frontends/sp8870.c +++ b/drivers/media/dvb-frontends/sp8870.c | |||
@@ -188,7 +188,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05) | |||
188 | break; | 188 | break; |
189 | default: | 189 | default: |
190 | return -EINVAL; | 190 | return -EINVAL; |
191 | }; | 191 | } |
192 | 192 | ||
193 | switch (p->hierarchy) { | 193 | switch (p->hierarchy) { |
194 | case HIERARCHY_NONE: | 194 | case HIERARCHY_NONE: |
@@ -207,7 +207,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05) | |||
207 | break; | 207 | break; |
208 | default: | 208 | default: |
209 | return -EINVAL; | 209 | return -EINVAL; |
210 | }; | 210 | } |
211 | 211 | ||
212 | switch (p->code_rate_HP) { | 212 | switch (p->code_rate_HP) { |
213 | case FEC_1_2: | 213 | case FEC_1_2: |
@@ -229,7 +229,7 @@ static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05) | |||
229 | break; | 229 | break; |
230 | default: | 230 | default: |
231 | return -EINVAL; | 231 | return -EINVAL; |
232 | }; | 232 | } |
233 | 233 | ||
234 | if (known_parameters) | 234 | if (known_parameters) |
235 | *reg0xc05 |= (2 << 1); /* use specified parameters */ | 235 | *reg0xc05 |= (2 << 1); /* use specified parameters */ |
diff --git a/drivers/media/dvb-frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c index f4096ccb226e..1bb81b5ae6e0 100644 --- a/drivers/media/dvb-frontends/sp887x.c +++ b/drivers/media/dvb-frontends/sp887x.c | |||
@@ -229,7 +229,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05) | |||
229 | break; | 229 | break; |
230 | default: | 230 | default: |
231 | return -EINVAL; | 231 | return -EINVAL; |
232 | }; | 232 | } |
233 | 233 | ||
234 | switch (p->hierarchy) { | 234 | switch (p->hierarchy) { |
235 | case HIERARCHY_NONE: | 235 | case HIERARCHY_NONE: |
@@ -248,7 +248,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05) | |||
248 | break; | 248 | break; |
249 | default: | 249 | default: |
250 | return -EINVAL; | 250 | return -EINVAL; |
251 | }; | 251 | } |
252 | 252 | ||
253 | switch (p->code_rate_HP) { | 253 | switch (p->code_rate_HP) { |
254 | case FEC_1_2: | 254 | case FEC_1_2: |
@@ -270,7 +270,7 @@ static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05) | |||
270 | break; | 270 | break; |
271 | default: | 271 | default: |
272 | return -EINVAL; | 272 | return -EINVAL; |
273 | }; | 273 | } |
274 | 274 | ||
275 | if (known_parameters) | 275 | if (known_parameters) |
276 | *reg0xc05 |= (2 << 1); /* use specified parameters */ | 276 | *reg0xc05 |= (2 << 1); /* use specified parameters */ |
diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index 2e93e65d2cdb..45f9523f968f 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c | |||
@@ -575,8 +575,8 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe, | |||
575 | struct stb6100_state *state = NULL; | 575 | struct stb6100_state *state = NULL; |
576 | 576 | ||
577 | state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL); | 577 | state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL); |
578 | if (state == NULL) | 578 | if (!state) |
579 | goto error; | 579 | return NULL; |
580 | 580 | ||
581 | state->config = config; | 581 | state->config = config; |
582 | state->i2c = i2c; | 582 | state->i2c = i2c; |
@@ -587,10 +587,6 @@ struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe, | |||
587 | 587 | ||
588 | printk("%s: Attaching STB6100 \n", __func__); | 588 | printk("%s: Attaching STB6100 \n", __func__); |
589 | return fe; | 589 | return fe; |
590 | |||
591 | error: | ||
592 | kfree(state); | ||
593 | return NULL; | ||
594 | } | 590 | } |
595 | 591 | ||
596 | static int stb6100_release(struct dvb_frontend *fe) | 592 | static int stb6100_release(struct dvb_frontend *fe) |
diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index 057b5f8effc0..92a6075cd82f 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c | |||
@@ -199,7 +199,7 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout) | |||
199 | return -ETIMEDOUT; | 199 | return -ETIMEDOUT; |
200 | } | 200 | } |
201 | msleep(10); | 201 | msleep(10); |
202 | }; | 202 | } |
203 | 203 | ||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
@@ -216,7 +216,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout) | |||
216 | return -ETIMEDOUT; | 216 | return -ETIMEDOUT; |
217 | } | 217 | } |
218 | msleep(10); | 218 | msleep(10); |
219 | }; | 219 | } |
220 | 220 | ||
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
@@ -387,7 +387,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag | |||
387 | break; | 387 | break; |
388 | default: | 388 | default: |
389 | return -EINVAL; | 389 | return -EINVAL; |
390 | }; | 390 | } |
391 | 391 | ||
392 | if (state->config->op0_off) | 392 | if (state->config->op0_off) |
393 | reg0x0c &= ~0x10; | 393 | reg0x0c &= ~0x10; |
diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index 7f1badaf0d03..262dfa503c2a 100644 --- a/drivers/media/dvb-frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c | |||
@@ -1552,8 +1552,8 @@ static int stv0900_status(struct stv0900_internal *intp, | |||
1552 | bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000) | 1552 | bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000) |
1553 | * (tsbitrate1_val << 8 | tsbitrate0_val); | 1553 | * (tsbitrate1_val << 8 | tsbitrate0_val); |
1554 | bitrate /= 16384; | 1554 | bitrate /= 16384; |
1555 | dprintk("TS bitrate = %d Mbit/sec \n", bitrate); | 1555 | dprintk("TS bitrate = %d Mbit/sec\n", bitrate); |
1556 | }; | 1556 | } |
1557 | 1557 | ||
1558 | return locked; | 1558 | return locked; |
1559 | } | 1559 | } |
diff --git a/drivers/media/dvb-frontends/tda665x.c b/drivers/media/dvb-frontends/tda665x.c index 2c1c759a4f42..63cc12378d9a 100644 --- a/drivers/media/dvb-frontends/tda665x.c +++ b/drivers/media/dvb-frontends/tda665x.c | |||
@@ -228,8 +228,8 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, | |||
228 | struct dvb_tuner_info *info; | 228 | struct dvb_tuner_info *info; |
229 | 229 | ||
230 | state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL); | 230 | state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL); |
231 | if (state == NULL) | 231 | if (!state) |
232 | goto exit; | 232 | return NULL; |
233 | 233 | ||
234 | state->config = config; | 234 | state->config = config; |
235 | state->i2c = i2c; | 235 | state->i2c = i2c; |
@@ -246,10 +246,6 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, | |||
246 | printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); | 246 | printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); |
247 | 247 | ||
248 | return fe; | 248 | return fe; |
249 | |||
250 | exit: | ||
251 | kfree(state); | ||
252 | return NULL; | ||
253 | } | 249 | } |
254 | EXPORT_SYMBOL(tda665x_attach); | 250 | EXPORT_SYMBOL(tda665x_attach); |
255 | 251 | ||
diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index 15912c96926a..9d08350fe4b0 100644 --- a/drivers/media/dvb-frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c | |||
@@ -175,7 +175,7 @@ static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout) | |||
175 | !(tda8083_readreg(state, 0x02) & 0x80)) | 175 | !(tda8083_readreg(state, 0x02) & 0x80)) |
176 | { | 176 | { |
177 | msleep(50); | 177 | msleep(50); |
178 | }; | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
181 | static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone) | 181 | 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 | |||
215 | break; | 215 | break; |
216 | default: | 216 | default: |
217 | return -EINVAL; | 217 | return -EINVAL; |
218 | }; | 218 | } |
219 | 219 | ||
220 | tda8083_wait_diseqc_fifo (state, 100); | 220 | tda8083_wait_diseqc_fifo (state, 100); |
221 | 221 | ||
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index d8eac3e30a7e..2cee69e34184 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c | |||
@@ -599,7 +599,7 @@ static void cx23885_initialize(struct i2c_client *client) | |||
599 | cx25840_write4(client, 0x114, 0x01bf0c9e); | 599 | cx25840_write4(client, 0x114, 0x01bf0c9e); |
600 | cx25840_write4(client, 0x110, 0x000a030c); | 600 | cx25840_write4(client, 0x110, 0x000a030c); |
601 | break; | 601 | break; |
602 | }; | 602 | } |
603 | 603 | ||
604 | /* ADC2 input select */ | 604 | /* ADC2 input select */ |
605 | cx25840_write(client, 0x102, 0x10); | 605 | cx25840_write(client, 0x102, 0x10); |
diff --git a/drivers/media/i2c/m5mols/m5mols.h b/drivers/media/i2c/m5mols/m5mols.h index 86c815be348c..90a6c520f115 100644 --- a/drivers/media/i2c/m5mols/m5mols.h +++ b/drivers/media/i2c/m5mols/m5mols.h | |||
@@ -16,9 +16,17 @@ | |||
16 | #ifndef M5MOLS_H | 16 | #ifndef M5MOLS_H |
17 | #define M5MOLS_H | 17 | #define M5MOLS_H |
18 | 18 | ||
19 | #include <linux/sizes.h> | ||
19 | #include <media/v4l2-subdev.h> | 20 | #include <media/v4l2-subdev.h> |
20 | #include "m5mols_reg.h" | 21 | #include "m5mols_reg.h" |
21 | 22 | ||
23 | |||
24 | /* An amount of data transmitted in addition to the value | ||
25 | * determined by CAPP_JPEG_SIZE_MAX register. | ||
26 | */ | ||
27 | #define M5MOLS_JPEG_TAGS_SIZE 0x20000 | ||
28 | #define M5MOLS_MAIN_JPEG_SIZE_MAX (5 * SZ_1M) | ||
29 | |||
22 | extern int m5mols_debug; | 30 | extern int m5mols_debug; |
23 | 31 | ||
24 | enum m5mols_restype { | 32 | enum m5mols_restype { |
@@ -67,12 +75,14 @@ struct m5mols_exif { | |||
67 | /** | 75 | /** |
68 | * struct m5mols_capture - Structure for the capture capability | 76 | * struct m5mols_capture - Structure for the capture capability |
69 | * @exif: EXIF information | 77 | * @exif: EXIF information |
78 | * @buf_size: internal JPEG frame buffer size, in bytes | ||
70 | * @main: size in bytes of the main image | 79 | * @main: size in bytes of the main image |
71 | * @thumb: size in bytes of the thumb image, if it was accompanied | 80 | * @thumb: size in bytes of the thumb image, if it was accompanied |
72 | * @total: total size in bytes of the produced image | 81 | * @total: total size in bytes of the produced image |
73 | */ | 82 | */ |
74 | struct m5mols_capture { | 83 | struct m5mols_capture { |
75 | struct m5mols_exif exif; | 84 | struct m5mols_exif exif; |
85 | unsigned int buf_size; | ||
76 | u32 main; | 86 | u32 main; |
77 | u32 thumb; | 87 | u32 thumb; |
78 | u32 total; | 88 | u32 total; |
diff --git a/drivers/media/i2c/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c index cb243bd278ce..ab34ccedf31e 100644 --- a/drivers/media/i2c/m5mols/m5mols_capture.c +++ b/drivers/media/i2c/m5mols/m5mols_capture.c | |||
@@ -105,6 +105,7 @@ static int m5mols_capture_info(struct m5mols_info *info) | |||
105 | 105 | ||
106 | int m5mols_start_capture(struct m5mols_info *info) | 106 | int m5mols_start_capture(struct m5mols_info *info) |
107 | { | 107 | { |
108 | unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE; | ||
108 | struct v4l2_subdev *sd = &info->sd; | 109 | struct v4l2_subdev *sd = &info->sd; |
109 | int ret; | 110 | int ret; |
110 | 111 | ||
@@ -121,6 +122,8 @@ int m5mols_start_capture(struct m5mols_info *info) | |||
121 | if (!ret) | 122 | if (!ret) |
122 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution); | 123 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution); |
123 | if (!ret) | 124 | if (!ret) |
125 | ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize); | ||
126 | if (!ret) | ||
124 | ret = m5mols_set_mode(info, REG_CAPTURE); | 127 | ret = m5mols_set_mode(info, REG_CAPTURE); |
125 | if (!ret) | 128 | if (!ret) |
126 | /* Wait until a frame is captured to ISP internal memory */ | 129 | /* Wait until a frame is captured to ISP internal memory */ |
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 2f490ef26c38..8131d651de9e 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c | |||
@@ -599,6 +599,51 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
599 | return ret; | 599 | return ret; |
600 | } | 600 | } |
601 | 601 | ||
602 | static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, | ||
603 | struct v4l2_mbus_frame_desc *fd) | ||
604 | { | ||
605 | struct m5mols_info *info = to_m5mols(sd); | ||
606 | |||
607 | if (pad != 0 || fd == NULL) | ||
608 | return -EINVAL; | ||
609 | |||
610 | mutex_lock(&info->lock); | ||
611 | /* | ||
612 | * .get_frame_desc is only used for compressed formats, | ||
613 | * thus we always return the capture frame parameters here. | ||
614 | */ | ||
615 | fd->entry[0].length = info->cap.buf_size; | ||
616 | fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code; | ||
617 | mutex_unlock(&info->lock); | ||
618 | |||
619 | fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX; | ||
620 | fd->num_entries = 1; | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad, | ||
626 | struct v4l2_mbus_frame_desc *fd) | ||
627 | { | ||
628 | struct m5mols_info *info = to_m5mols(sd); | ||
629 | struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE]; | ||
630 | |||
631 | if (pad != 0 || fd == NULL) | ||
632 | return -EINVAL; | ||
633 | |||
634 | fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX; | ||
635 | fd->num_entries = 1; | ||
636 | fd->entry[0].length = clamp_t(u32, fd->entry[0].length, | ||
637 | mf->width * mf->height, | ||
638 | M5MOLS_MAIN_JPEG_SIZE_MAX); | ||
639 | mutex_lock(&info->lock); | ||
640 | info->cap.buf_size = fd->entry[0].length; | ||
641 | mutex_unlock(&info->lock); | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | |||
602 | static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, | 647 | static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, |
603 | struct v4l2_subdev_fh *fh, | 648 | struct v4l2_subdev_fh *fh, |
604 | struct v4l2_subdev_mbus_code_enum *code) | 649 | struct v4l2_subdev_mbus_code_enum *code) |
@@ -615,6 +660,8 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = { | |||
615 | .enum_mbus_code = m5mols_enum_mbus_code, | 660 | .enum_mbus_code = m5mols_enum_mbus_code, |
616 | .get_fmt = m5mols_get_fmt, | 661 | .get_fmt = m5mols_get_fmt, |
617 | .set_fmt = m5mols_set_fmt, | 662 | .set_fmt = m5mols_set_fmt, |
663 | .get_frame_desc = m5mols_get_frame_desc, | ||
664 | .set_frame_desc = m5mols_set_frame_desc, | ||
618 | }; | 665 | }; |
619 | 666 | ||
620 | /** | 667 | /** |
diff --git a/drivers/media/i2c/m5mols/m5mols_reg.h b/drivers/media/i2c/m5mols/m5mols_reg.h index 14d4be72aeff..58d8027508df 100644 --- a/drivers/media/i2c/m5mols/m5mols_reg.h +++ b/drivers/media/i2c/m5mols/m5mols_reg.h | |||
@@ -310,6 +310,7 @@ | |||
310 | #define REG_JPEG 0x10 | 310 | #define REG_JPEG 0x10 |
311 | 311 | ||
312 | #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1) | 312 | #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1) |
313 | #define CAPP_JPEG_SIZE_MAX I2C_REG(CAT_CAPT_PARM, 0x0f, 4) | ||
313 | #define CAPP_JPEG_RATIO I2C_REG(CAT_CAPT_PARM, 0x17, 1) | 314 | #define CAPP_JPEG_RATIO I2C_REG(CAT_CAPT_PARM, 0x17, 1) |
314 | 315 | ||
315 | #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1) | 316 | #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1) |
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 2c0f4077c491..e32833262d32 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c | |||
@@ -574,7 +574,6 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev, | |||
574 | * V4L2 subdev control operations | 574 | * V4L2 subdev control operations |
575 | */ | 575 | */ |
576 | 576 | ||
577 | #define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001) | ||
578 | #define V4L2_CID_BLC_AUTO (V4L2_CID_USER_BASE | 0x1002) | 577 | #define V4L2_CID_BLC_AUTO (V4L2_CID_USER_BASE | 0x1002) |
579 | #define V4L2_CID_BLC_TARGET_LEVEL (V4L2_CID_USER_BASE | 0x1003) | 578 | #define V4L2_CID_BLC_TARGET_LEVEL (V4L2_CID_USER_BASE | 0x1003) |
580 | #define V4L2_CID_BLC_ANALOG_OFFSET (V4L2_CID_USER_BASE | 0x1004) | 579 | #define V4L2_CID_BLC_ANALOG_OFFSET (V4L2_CID_USER_BASE | 0x1004) |
@@ -740,18 +739,6 @@ static const char * const mt9p031_test_pattern_menu[] = { | |||
740 | static const struct v4l2_ctrl_config mt9p031_ctrls[] = { | 739 | static const struct v4l2_ctrl_config mt9p031_ctrls[] = { |
741 | { | 740 | { |
742 | .ops = &mt9p031_ctrl_ops, | 741 | .ops = &mt9p031_ctrl_ops, |
743 | .id = V4L2_CID_TEST_PATTERN, | ||
744 | .type = V4L2_CTRL_TYPE_MENU, | ||
745 | .name = "Test Pattern", | ||
746 | .min = 0, | ||
747 | .max = ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, | ||
748 | .step = 0, | ||
749 | .def = 0, | ||
750 | .flags = 0, | ||
751 | .menu_skip_mask = 0, | ||
752 | .qmenu = mt9p031_test_pattern_menu, | ||
753 | }, { | ||
754 | .ops = &mt9p031_ctrl_ops, | ||
755 | .id = V4L2_CID_BLC_AUTO, | 742 | .id = V4L2_CID_BLC_AUTO, |
756 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 743 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
757 | .name = "BLC, Auto", | 744 | .name = "BLC, Auto", |
@@ -950,7 +937,7 @@ static int mt9p031_probe(struct i2c_client *client, | |||
950 | mt9p031->model = did->driver_data; | 937 | mt9p031->model = did->driver_data; |
951 | mt9p031->reset = -1; | 938 | mt9p031->reset = -1; |
952 | 939 | ||
953 | v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5); | 940 | v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6); |
954 | 941 | ||
955 | v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, | 942 | v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, |
956 | V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN, | 943 | V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN, |
@@ -966,6 +953,10 @@ static int mt9p031_probe(struct i2c_client *client, | |||
966 | v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, | 953 | v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, |
967 | V4L2_CID_PIXEL_RATE, pdata->target_freq, | 954 | V4L2_CID_PIXEL_RATE, pdata->target_freq, |
968 | pdata->target_freq, 1, pdata->target_freq); | 955 | pdata->target_freq, 1, pdata->target_freq); |
956 | v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops, | ||
957 | V4L2_CID_TEST_PATTERN, | ||
958 | ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0, | ||
959 | 0, mt9p031_test_pattern_menu); | ||
969 | 960 | ||
970 | for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i) | 961 | for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i) |
971 | v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL); | 962 | v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL); |
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c index 6d343adf891d..2e189d8b71bb 100644 --- a/drivers/media/i2c/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c | |||
@@ -371,7 +371,7 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev, | |||
371 | * V4L2 subdev control operations | 371 | * V4L2 subdev control operations |
372 | */ | 372 | */ |
373 | 373 | ||
374 | #define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001) | 374 | #define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001) |
375 | #define V4L2_CID_BLACK_LEVEL_AUTO (V4L2_CID_USER_BASE | 0x1002) | 375 | #define V4L2_CID_BLACK_LEVEL_AUTO (V4L2_CID_USER_BASE | 0x1002) |
376 | #define V4L2_CID_BLACK_LEVEL_OFFSET (V4L2_CID_USER_BASE | 0x1003) | 376 | #define V4L2_CID_BLACK_LEVEL_OFFSET (V4L2_CID_USER_BASE | 0x1003) |
377 | #define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004) | 377 | #define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004) |
@@ -487,12 +487,11 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl) | |||
487 | ctrl->val >> 16); | 487 | ctrl->val >> 16); |
488 | 488 | ||
489 | case V4L2_CID_TEST_PATTERN: | 489 | case V4L2_CID_TEST_PATTERN: |
490 | ret = mt9t001_set_output_control(mt9t001, | 490 | return mt9t001_set_output_control(mt9t001, |
491 | ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA, | 491 | ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA, |
492 | ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0); | 492 | ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0); |
493 | if (ret < 0) | ||
494 | return ret; | ||
495 | 493 | ||
494 | case V4L2_CID_TEST_PATTERN_COLOR: | ||
496 | return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2); | 495 | return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2); |
497 | 496 | ||
498 | case V4L2_CID_BLACK_LEVEL_AUTO: | 497 | case V4L2_CID_BLACK_LEVEL_AUTO: |
@@ -533,12 +532,17 @@ static struct v4l2_ctrl_ops mt9t001_ctrl_ops = { | |||
533 | .s_ctrl = mt9t001_s_ctrl, | 532 | .s_ctrl = mt9t001_s_ctrl, |
534 | }; | 533 | }; |
535 | 534 | ||
535 | static const char * const mt9t001_test_pattern_menu[] = { | ||
536 | "Disabled", | ||
537 | "Enabled", | ||
538 | }; | ||
539 | |||
536 | static const struct v4l2_ctrl_config mt9t001_ctrls[] = { | 540 | static const struct v4l2_ctrl_config mt9t001_ctrls[] = { |
537 | { | 541 | { |
538 | .ops = &mt9t001_ctrl_ops, | 542 | .ops = &mt9t001_ctrl_ops, |
539 | .id = V4L2_CID_TEST_PATTERN, | 543 | .id = V4L2_CID_TEST_PATTERN_COLOR, |
540 | .type = V4L2_CTRL_TYPE_INTEGER, | 544 | .type = V4L2_CTRL_TYPE_INTEGER, |
541 | .name = "Test pattern", | 545 | .name = "Test Pattern Color", |
542 | .min = 0, | 546 | .min = 0, |
543 | .max = 1023, | 547 | .max = 1023, |
544 | .step = 1, | 548 | .step = 1, |
@@ -741,7 +745,7 @@ static int mt9t001_probe(struct i2c_client *client, | |||
741 | return -ENOMEM; | 745 | return -ENOMEM; |
742 | 746 | ||
743 | v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) + | 747 | v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) + |
744 | ARRAY_SIZE(mt9t001_gains) + 3); | 748 | ARRAY_SIZE(mt9t001_gains) + 4); |
745 | 749 | ||
746 | v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, | 750 | v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, |
747 | V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN, | 751 | V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN, |
@@ -752,6 +756,10 @@ static int mt9t001_probe(struct i2c_client *client, | |||
752 | v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, | 756 | v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, |
753 | V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk, | 757 | V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk, |
754 | 1, pdata->ext_clk); | 758 | 1, pdata->ext_clk); |
759 | v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops, | ||
760 | V4L2_CID_TEST_PATTERN, | ||
761 | ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0, | ||
762 | 0, mt9t001_test_pattern_menu); | ||
755 | 763 | ||
756 | for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i) | 764 | for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i) |
757 | v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL); | 765 | v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL); |
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index e2177405dad2..3f356cb28256 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c | |||
@@ -141,6 +141,10 @@ struct mt9v032 { | |||
141 | u16 chip_control; | 141 | u16 chip_control; |
142 | u16 aec_agc; | 142 | u16 aec_agc; |
143 | u16 hblank; | 143 | u16 hblank; |
144 | struct { | ||
145 | struct v4l2_ctrl *test_pattern; | ||
146 | struct v4l2_ctrl *test_pattern_color; | ||
147 | }; | ||
144 | }; | 148 | }; |
145 | 149 | ||
146 | static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) | 150 | static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) |
@@ -500,7 +504,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev, | |||
500 | * V4L2 subdev control operations | 504 | * V4L2 subdev control operations |
501 | */ | 505 | */ |
502 | 506 | ||
503 | #define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001) | 507 | #define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001) |
504 | 508 | ||
505 | static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | 509 | static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) |
506 | { | 510 | { |
@@ -545,7 +549,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | |||
545 | break; | 549 | break; |
546 | 550 | ||
547 | case V4L2_CID_TEST_PATTERN: | 551 | case V4L2_CID_TEST_PATTERN: |
548 | switch (ctrl->val) { | 552 | switch (mt9v032->test_pattern->val) { |
549 | case 0: | 553 | case 0: |
550 | data = 0; | 554 | data = 0; |
551 | break; | 555 | break; |
@@ -562,13 +566,13 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | |||
562 | | MT9V032_TEST_PATTERN_ENABLE; | 566 | | MT9V032_TEST_PATTERN_ENABLE; |
563 | break; | 567 | break; |
564 | default: | 568 | default: |
565 | data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT) | 569 | data = (mt9v032->test_pattern_color->val << |
570 | MT9V032_TEST_PATTERN_DATA_SHIFT) | ||
566 | | MT9V032_TEST_PATTERN_USE_DATA | 571 | | MT9V032_TEST_PATTERN_USE_DATA |
567 | | MT9V032_TEST_PATTERN_ENABLE | 572 | | MT9V032_TEST_PATTERN_ENABLE |
568 | | MT9V032_TEST_PATTERN_FLIP; | 573 | | MT9V032_TEST_PATTERN_FLIP; |
569 | break; | 574 | break; |
570 | } | 575 | } |
571 | |||
572 | return mt9v032_write(client, MT9V032_TEST_PATTERN, data); | 576 | return mt9v032_write(client, MT9V032_TEST_PATTERN, data); |
573 | } | 577 | } |
574 | 578 | ||
@@ -579,18 +583,24 @@ static struct v4l2_ctrl_ops mt9v032_ctrl_ops = { | |||
579 | .s_ctrl = mt9v032_s_ctrl, | 583 | .s_ctrl = mt9v032_s_ctrl, |
580 | }; | 584 | }; |
581 | 585 | ||
582 | static const struct v4l2_ctrl_config mt9v032_ctrls[] = { | 586 | static const char * const mt9v032_test_pattern_menu[] = { |
583 | { | 587 | "Disabled", |
584 | .ops = &mt9v032_ctrl_ops, | 588 | "Gray Vertical Shade", |
585 | .id = V4L2_CID_TEST_PATTERN, | 589 | "Gray Horizontal Shade", |
586 | .type = V4L2_CTRL_TYPE_INTEGER, | 590 | "Gray Diagonal Shade", |
587 | .name = "Test pattern", | 591 | "Plain", |
588 | .min = 0, | 592 | }; |
589 | .max = 1023, | 593 | |
590 | .step = 1, | 594 | static const struct v4l2_ctrl_config mt9v032_test_pattern_color = { |
591 | .def = 0, | 595 | .ops = &mt9v032_ctrl_ops, |
592 | .flags = 0, | 596 | .id = V4L2_CID_TEST_PATTERN_COLOR, |
593 | } | 597 | .type = V4L2_CTRL_TYPE_INTEGER, |
598 | .name = "Test Pattern Color", | ||
599 | .min = 0, | ||
600 | .max = 1023, | ||
601 | .step = 1, | ||
602 | .def = 0, | ||
603 | .flags = 0, | ||
594 | }; | 604 | }; |
595 | 605 | ||
596 | /* ----------------------------------------------------------------------------- | 606 | /* ----------------------------------------------------------------------------- |
@@ -741,7 +751,7 @@ static int mt9v032_probe(struct i2c_client *client, | |||
741 | mutex_init(&mt9v032->power_lock); | 751 | mutex_init(&mt9v032->power_lock); |
742 | mt9v032->pdata = pdata; | 752 | mt9v032->pdata = pdata; |
743 | 753 | ||
744 | v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 8); | 754 | v4l2_ctrl_handler_init(&mt9v032->ctrls, 10); |
745 | 755 | ||
746 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | 756 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, |
747 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | 757 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); |
@@ -763,6 +773,14 @@ static int mt9v032_probe(struct i2c_client *client, | |||
763 | V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN, | 773 | V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN, |
764 | MT9V032_VERTICAL_BLANKING_MAX, 1, | 774 | MT9V032_VERTICAL_BLANKING_MAX, 1, |
765 | MT9V032_VERTICAL_BLANKING_DEF); | 775 | MT9V032_VERTICAL_BLANKING_DEF); |
776 | mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls, | ||
777 | &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN, | ||
778 | ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0, | ||
779 | mt9v032_test_pattern_menu); | ||
780 | mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls, | ||
781 | &mt9v032_test_pattern_color, NULL); | ||
782 | |||
783 | v4l2_ctrl_cluster(2, &mt9v032->test_pattern); | ||
766 | 784 | ||
767 | mt9v032->pixel_rate = | 785 | mt9v032->pixel_rate = |
768 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | 786 | v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, |
@@ -784,8 +802,6 @@ static int mt9v032_probe(struct i2c_client *client, | |||
784 | v4l2_ctrl_cluster(2, &mt9v032->link_freq); | 802 | v4l2_ctrl_cluster(2, &mt9v032->link_freq); |
785 | } | 803 | } |
786 | 804 | ||
787 | for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i) | ||
788 | v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL); | ||
789 | 805 | ||
790 | mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; | 806 | mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; |
791 | 807 | ||
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index 78ac5744cb5d..d2d298b6354e 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c | |||
@@ -684,6 +684,11 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl) | |||
684 | &container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev; | 684 | &container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev; |
685 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 685 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
686 | u8 val; | 686 | u8 val; |
687 | int ret; | ||
688 | |||
689 | ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS); | ||
690 | if (ret < 0) | ||
691 | return ret; | ||
687 | 692 | ||
688 | switch (ctrl->id) { | 693 | switch (ctrl->id) { |
689 | case V4L2_CID_VFLIP: | 694 | case V4L2_CID_VFLIP: |
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index e5c0eedebc58..c31cc04fffd2 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c | |||
@@ -28,6 +28,18 @@ | |||
28 | #include <media/v4l2-subdev.h> | 28 | #include <media/v4l2-subdev.h> |
29 | #include <media/v4l2-chip-ident.h> | 29 | #include <media/v4l2-chip-ident.h> |
30 | 30 | ||
31 | #define THS7303_CHANNEL_1 1 | ||
32 | #define THS7303_CHANNEL_2 2 | ||
33 | #define THS7303_CHANNEL_3 3 | ||
34 | |||
35 | enum ths7303_filter_mode { | ||
36 | THS7303_FILTER_MODE_480I_576I, | ||
37 | THS7303_FILTER_MODE_480P_576P, | ||
38 | THS7303_FILTER_MODE_720P_1080I, | ||
39 | THS7303_FILTER_MODE_1080P, | ||
40 | THS7303_FILTER_MODE_DISABLE | ||
41 | }; | ||
42 | |||
31 | MODULE_DESCRIPTION("TI THS7303 video amplifier driver"); | 43 | MODULE_DESCRIPTION("TI THS7303 video amplifier driver"); |
32 | MODULE_AUTHOR("Chaithrika U S"); | 44 | MODULE_AUTHOR("Chaithrika U S"); |
33 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
@@ -37,35 +49,96 @@ module_param(debug, int, 0644); | |||
37 | MODULE_PARM_DESC(debug, "Debug level 0-1"); | 49 | MODULE_PARM_DESC(debug, "Debug level 0-1"); |
38 | 50 | ||
39 | /* following function is used to set ths7303 */ | 51 | /* following function is used to set ths7303 */ |
40 | static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std) | 52 | int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode) |
41 | { | 53 | { |
54 | u8 input_bias_chroma = 3; | ||
55 | u8 input_bias_luma = 3; | ||
56 | int disable = 0; | ||
42 | int err = 0; | 57 | int err = 0; |
43 | u8 val; | 58 | u8 val = 0; |
44 | struct i2c_client *client; | 59 | u8 temp; |
45 | 60 | ||
46 | client = v4l2_get_subdevdata(sd); | 61 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
47 | 62 | ||
48 | if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) { | 63 | if (!client) |
49 | val = 0x02; | 64 | return -EINVAL; |
50 | v4l2_dbg(1, debug, sd, "setting value for SDTV format\n"); | 65 | |
51 | } else { | 66 | switch (mode) { |
52 | val = 0x00; | 67 | case THS7303_FILTER_MODE_1080P: |
53 | v4l2_dbg(1, debug, sd, "disabling all channels\n"); | 68 | val = (3 << 6); |
69 | val |= (3 << 3); | ||
70 | break; | ||
71 | case THS7303_FILTER_MODE_720P_1080I: | ||
72 | val = (2 << 6); | ||
73 | val |= (2 << 3); | ||
74 | break; | ||
75 | case THS7303_FILTER_MODE_480P_576P: | ||
76 | val = (1 << 6); | ||
77 | val |= (1 << 3); | ||
78 | break; | ||
79 | case THS7303_FILTER_MODE_480I_576I: | ||
80 | break; | ||
81 | case THS7303_FILTER_MODE_DISABLE: | ||
82 | pr_info("mode disabled\n"); | ||
83 | /* disable all channels */ | ||
84 | disable = 1; | ||
85 | default: | ||
86 | /* disable all channels */ | ||
87 | disable = 1; | ||
54 | } | 88 | } |
89 | /* Setup channel 2 - Luma - Green */ | ||
90 | temp = val; | ||
91 | if (!disable) | ||
92 | val |= input_bias_luma; | ||
93 | err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_2, val); | ||
94 | if (err) | ||
95 | goto out; | ||
55 | 96 | ||
56 | err |= i2c_smbus_write_byte_data(client, 0x01, val); | 97 | /* setup two chroma channels */ |
57 | err |= i2c_smbus_write_byte_data(client, 0x02, val); | 98 | if (!disable) |
58 | err |= i2c_smbus_write_byte_data(client, 0x03, val); | 99 | temp |= input_bias_chroma; |
59 | 100 | ||
101 | err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_1, temp); | ||
60 | if (err) | 102 | if (err) |
61 | v4l2_err(sd, "write failed\n"); | 103 | goto out; |
62 | 104 | ||
105 | err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_3, temp); | ||
106 | if (err) | ||
107 | goto out; | ||
108 | return err; | ||
109 | out: | ||
110 | pr_info("write byte data failed\n"); | ||
63 | return err; | 111 | return err; |
64 | } | 112 | } |
65 | 113 | ||
66 | static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) | 114 | static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) |
67 | { | 115 | { |
68 | return ths7303_setvalue(sd, norm); | 116 | if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) |
117 | return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I); | ||
118 | else | ||
119 | return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE); | ||
120 | } | ||
121 | |||
122 | /* for setting filter for HD output */ | ||
123 | static int ths7303_s_dv_timings(struct v4l2_subdev *sd, | ||
124 | struct v4l2_dv_timings *dv_timings) | ||
125 | { | ||
126 | u32 height = dv_timings->bt.height; | ||
127 | int interlaced = dv_timings->bt.interlaced; | ||
128 | int res = 0; | ||
129 | |||
130 | if (height == 1080 && !interlaced) | ||
131 | res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P); | ||
132 | else if ((height == 720 && !interlaced) || | ||
133 | (height == 1080 && interlaced)) | ||
134 | res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I); | ||
135 | else if ((height == 480 || height == 576) && !interlaced) | ||
136 | res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P); | ||
137 | else | ||
138 | /* disable all channels */ | ||
139 | res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE); | ||
140 | |||
141 | return res; | ||
69 | } | 142 | } |
70 | 143 | ||
71 | static int ths7303_g_chip_ident(struct v4l2_subdev *sd, | 144 | static int ths7303_g_chip_ident(struct v4l2_subdev *sd, |
@@ -78,6 +151,7 @@ static int ths7303_g_chip_ident(struct v4l2_subdev *sd, | |||
78 | 151 | ||
79 | static const struct v4l2_subdev_video_ops ths7303_video_ops = { | 152 | static const struct v4l2_subdev_video_ops ths7303_video_ops = { |
80 | .s_std_output = ths7303_s_std_output, | 153 | .s_std_output = ths7303_s_std_output, |
154 | .s_dv_timings = ths7303_s_dv_timings, | ||
81 | }; | 155 | }; |
82 | 156 | ||
83 | static const struct v4l2_subdev_core_ops ths7303_core_ops = { | 157 | static const struct v4l2_subdev_core_ops ths7303_core_ops = { |
@@ -107,7 +181,7 @@ static int ths7303_probe(struct i2c_client *client, | |||
107 | 181 | ||
108 | v4l2_i2c_subdev_init(sd, client, &ths7303_ops); | 182 | v4l2_i2c_subdev_init(sd, client, &ths7303_ops); |
109 | 183 | ||
110 | return ths7303_setvalue(sd, std_id); | 184 | return ths7303_s_std_output(sd, std_id); |
111 | } | 185 | } |
112 | 186 | ||
113 | static int ths7303_remove(struct i2c_client *client) | 187 | static int ths7303_remove(struct i2c_client *client) |
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 1f3943bb87d5..d5e10215a28f 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c | |||
@@ -519,6 +519,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) | |||
519 | 519 | ||
520 | *std_id = V4L2_STD_UNKNOWN; | 520 | *std_id = V4L2_STD_UNKNOWN; |
521 | 521 | ||
522 | /* To query the standard the TVP514x must power on the ADCs. */ | ||
523 | if (!decoder->streaming) { | ||
524 | tvp514x_s_stream(sd, 1); | ||
525 | msleep(LOCK_RETRY_DELAY); | ||
526 | } | ||
527 | |||
522 | /* query the current standard */ | 528 | /* query the current standard */ |
523 | current_std = tvp514x_query_current_std(sd); | 529 | current_std = tvp514x_query_current_std(sd); |
524 | if (current_std == STD_INVALID) | 530 | if (current_std == STD_INVALID) |
@@ -625,25 +631,12 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, | |||
625 | int err; | 631 | int err; |
626 | enum tvp514x_input input_sel; | 632 | enum tvp514x_input input_sel; |
627 | enum tvp514x_output output_sel; | 633 | enum tvp514x_output output_sel; |
628 | u8 sync_lock_status, lock_mask; | ||
629 | int try_count = LOCK_RETRY_COUNT; | ||
630 | 634 | ||
631 | if ((input >= INPUT_INVALID) || | 635 | if ((input >= INPUT_INVALID) || |
632 | (output >= OUTPUT_INVALID)) | 636 | (output >= OUTPUT_INVALID)) |
633 | /* Index out of bound */ | 637 | /* Index out of bound */ |
634 | return -EINVAL; | 638 | return -EINVAL; |
635 | 639 | ||
636 | /* | ||
637 | * For the sequence streamon -> streamoff and again s_input | ||
638 | * it fails to lock the signal, since streamoff puts TVP514x | ||
639 | * into power off state which leads to failure in sub-sequent s_input. | ||
640 | * | ||
641 | * So power up the TVP514x device here, since it is important to lock | ||
642 | * the signal at this stage. | ||
643 | */ | ||
644 | if (!decoder->streaming) | ||
645 | tvp514x_s_stream(sd, 1); | ||
646 | |||
647 | input_sel = input; | 640 | input_sel = input; |
648 | output_sel = output; | 641 | output_sel = output; |
649 | 642 | ||
@@ -660,64 +653,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, | |||
660 | 653 | ||
661 | decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel; | 654 | decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel; |
662 | decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel; | 655 | decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel; |
663 | |||
664 | /* Clear status */ | ||
665 | msleep(LOCK_RETRY_DELAY); | ||
666 | err = | ||
667 | tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01); | ||
668 | if (err) | ||
669 | return err; | ||
670 | |||
671 | switch (input_sel) { | ||
672 | case INPUT_CVBS_VI1A: | ||
673 | case INPUT_CVBS_VI1B: | ||
674 | case INPUT_CVBS_VI1C: | ||
675 | case INPUT_CVBS_VI2A: | ||
676 | case INPUT_CVBS_VI2B: | ||
677 | case INPUT_CVBS_VI2C: | ||
678 | case INPUT_CVBS_VI3A: | ||
679 | case INPUT_CVBS_VI3B: | ||
680 | case INPUT_CVBS_VI3C: | ||
681 | case INPUT_CVBS_VI4A: | ||
682 | lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | | ||
683 | STATUS_HORZ_SYNC_LOCK_BIT | | ||
684 | STATUS_VIRT_SYNC_LOCK_BIT; | ||
685 | break; | ||
686 | |||
687 | case INPUT_SVIDEO_VI2A_VI1A: | ||
688 | case INPUT_SVIDEO_VI2B_VI1B: | ||
689 | case INPUT_SVIDEO_VI2C_VI1C: | ||
690 | case INPUT_SVIDEO_VI2A_VI3A: | ||
691 | case INPUT_SVIDEO_VI2B_VI3B: | ||
692 | case INPUT_SVIDEO_VI2C_VI3C: | ||
693 | case INPUT_SVIDEO_VI4A_VI1A: | ||
694 | case INPUT_SVIDEO_VI4A_VI1B: | ||
695 | case INPUT_SVIDEO_VI4A_VI1C: | ||
696 | case INPUT_SVIDEO_VI4A_VI3A: | ||
697 | case INPUT_SVIDEO_VI4A_VI3B: | ||
698 | case INPUT_SVIDEO_VI4A_VI3C: | ||
699 | lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | | ||
700 | STATUS_VIRT_SYNC_LOCK_BIT; | ||
701 | break; | ||
702 | /* Need to add other interfaces*/ | ||
703 | default: | ||
704 | return -EINVAL; | ||
705 | } | ||
706 | |||
707 | while (try_count-- > 0) { | ||
708 | /* Allow decoder to sync up with new input */ | ||
709 | msleep(LOCK_RETRY_DELAY); | ||
710 | |||
711 | sync_lock_status = tvp514x_read_reg(sd, | ||
712 | REG_STATUS1); | ||
713 | if (lock_mask == (sync_lock_status & lock_mask)) | ||
714 | /* Input detected */ | ||
715 | break; | ||
716 | } | ||
717 | |||
718 | if (try_count < 0) | ||
719 | return -EINVAL; | ||
720 | |||
721 | decoder->input = input; | 656 | decoder->input = input; |
722 | decoder->output = output; | 657 | decoder->output = output; |
723 | 658 | ||
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index b68918c97f66..56c6c77793d7 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c | |||
@@ -668,6 +668,12 @@ static const struct v4l2_queryctrl bttv_ctls[] = { | |||
668 | .default_value = 32768, | 668 | .default_value = 32768, |
669 | .type = V4L2_CTRL_TYPE_INTEGER, | 669 | .type = V4L2_CTRL_TYPE_INTEGER, |
670 | },{ | 670 | },{ |
671 | .id = V4L2_CID_COLOR_KILLER, | ||
672 | .name = "Color killer", | ||
673 | .minimum = 0, | ||
674 | .maximum = 1, | ||
675 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
676 | }, { | ||
671 | .id = V4L2_CID_HUE, | 677 | .id = V4L2_CID_HUE, |
672 | .name = "Hue", | 678 | .name = "Hue", |
673 | .minimum = 0, | 679 | .minimum = 0, |
@@ -1474,6 +1480,9 @@ static int bttv_g_ctrl(struct file *file, void *priv, | |||
1474 | case V4L2_CID_SATURATION: | 1480 | case V4L2_CID_SATURATION: |
1475 | c->value = btv->saturation; | 1481 | c->value = btv->saturation; |
1476 | break; | 1482 | break; |
1483 | case V4L2_CID_COLOR_KILLER: | ||
1484 | c->value = btv->opt_color_killer; | ||
1485 | break; | ||
1477 | 1486 | ||
1478 | case V4L2_CID_AUDIO_MUTE: | 1487 | case V4L2_CID_AUDIO_MUTE: |
1479 | case V4L2_CID_AUDIO_VOLUME: | 1488 | case V4L2_CID_AUDIO_VOLUME: |
@@ -1526,7 +1535,6 @@ static int bttv_s_ctrl(struct file *file, void *f, | |||
1526 | struct v4l2_control *c) | 1535 | struct v4l2_control *c) |
1527 | { | 1536 | { |
1528 | int err; | 1537 | int err; |
1529 | int val; | ||
1530 | struct bttv_fh *fh = f; | 1538 | struct bttv_fh *fh = f; |
1531 | struct bttv *btv = fh->btv; | 1539 | struct bttv *btv = fh->btv; |
1532 | 1540 | ||
@@ -1547,6 +1555,16 @@ static int bttv_s_ctrl(struct file *file, void *f, | |||
1547 | case V4L2_CID_SATURATION: | 1555 | case V4L2_CID_SATURATION: |
1548 | bt848_sat(btv, c->value); | 1556 | bt848_sat(btv, c->value); |
1549 | break; | 1557 | break; |
1558 | case V4L2_CID_COLOR_KILLER: | ||
1559 | btv->opt_color_killer = c->value; | ||
1560 | if (btv->opt_color_killer) { | ||
1561 | btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP); | ||
1562 | btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP); | ||
1563 | } else { | ||
1564 | btand(~BT848_SCLOOP_CKILL, BT848_E_SCLOOP); | ||
1565 | btand(~BT848_SCLOOP_CKILL, BT848_O_SCLOOP); | ||
1566 | } | ||
1567 | break; | ||
1550 | case V4L2_CID_AUDIO_MUTE: | 1568 | case V4L2_CID_AUDIO_MUTE: |
1551 | audio_mute(btv, c->value); | 1569 | audio_mute(btv, c->value); |
1552 | /* fall through */ | 1570 | /* fall through */ |
@@ -1564,9 +1582,13 @@ static int bttv_s_ctrl(struct file *file, void *f, | |||
1564 | 1582 | ||
1565 | case V4L2_CID_PRIVATE_CHROMA_AGC: | 1583 | case V4L2_CID_PRIVATE_CHROMA_AGC: |
1566 | btv->opt_chroma_agc = c->value; | 1584 | btv->opt_chroma_agc = c->value; |
1567 | val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; | 1585 | if (btv->opt_chroma_agc) { |
1568 | btwrite(val, BT848_E_SCLOOP); | 1586 | btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP); |
1569 | btwrite(val, BT848_O_SCLOOP); | 1587 | btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP); |
1588 | } else { | ||
1589 | btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP); | ||
1590 | btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP); | ||
1591 | } | ||
1570 | break; | 1592 | break; |
1571 | case V4L2_CID_PRIVATE_COMBFILTER: | 1593 | case V4L2_CID_PRIVATE_COMBFILTER: |
1572 | btv->opt_combfilter = c->value; | 1594 | btv->opt_combfilter = c->value; |
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 70fd4f23f605..9ec0adba236c 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h | |||
@@ -429,6 +429,7 @@ struct bttv { | |||
429 | int opt_lumafilter; | 429 | int opt_lumafilter; |
430 | int opt_automute; | 430 | int opt_automute; |
431 | int opt_chroma_agc; | 431 | int opt_chroma_agc; |
432 | int opt_color_killer; | ||
432 | int opt_adc_crush; | 433 | int opt_adc_crush; |
433 | int opt_vcr_hack; | 434 | int opt_vcr_hack; |
434 | int opt_whitecrush_upper; | 435 | int opt_whitecrush_upper; |
diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index ee3884fbc9ce..7d96fab7d246 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c | |||
@@ -646,7 +646,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct | |||
646 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !"); | 646 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !"); |
647 | default: | 647 | default: |
648 | result = -EOPNOTSUPP; | 648 | result = -EOPNOTSUPP; |
649 | }; | 649 | } |
650 | free_mem_and_exit: | 650 | free_mem_and_exit: |
651 | kfree (p_ca_message); | 651 | kfree (p_ca_message); |
652 | kfree (p_ca_slot_info); | 652 | kfree (p_ca_slot_info); |
diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c index aee7f0dacff1..495781ee4711 100644 --- a/drivers/media/pci/cx23885/altera-ci.c +++ b/drivers/media/pci/cx23885/altera-ci.c | |||
@@ -416,7 +416,7 @@ static void netup_read_ci_status(struct work_struct *work) | |||
416 | DVB_CA_EN50221_POLL_CAM_READY : 0); | 416 | DVB_CA_EN50221_POLL_CAM_READY : 0); |
417 | ci_dbg_print("%s: setting CI[1] status = 0x%x\n", | 417 | ci_dbg_print("%s: setting CI[1] status = 0x%x\n", |
418 | __func__, inter->state[1]->status); | 418 | __func__, inter->state[1]->status); |
419 | }; | 419 | } |
420 | 420 | ||
421 | if (inter->state[0] != NULL) { | 421 | if (inter->state[0] != NULL) { |
422 | inter->state[0]->status = | 422 | inter->state[0]->status = |
@@ -425,7 +425,7 @@ static void netup_read_ci_status(struct work_struct *work) | |||
425 | DVB_CA_EN50221_POLL_CAM_READY : 0); | 425 | DVB_CA_EN50221_POLL_CAM_READY : 0); |
426 | ci_dbg_print("%s: setting CI[0] status = 0x%x\n", | 426 | ci_dbg_print("%s: setting CI[0] status = 0x%x\n", |
427 | __func__, inter->state[0]->status); | 427 | __func__, inter->state[0]->status); |
428 | }; | 428 | } |
429 | } | 429 | } |
430 | 430 | ||
431 | /* CI irq handler */ | 431 | /* CI irq handler */ |
diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c index c9f15d6dec40..6617774a326a 100644 --- a/drivers/media/pci/cx23885/cimax2.c +++ b/drivers/media/pci/cx23885/cimax2.c | |||
@@ -193,7 +193,7 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, | |||
193 | 0, &store, 1); | 193 | 0, &store, 1); |
194 | if (ret != 0) | 194 | if (ret != 0) |
195 | return ret; | 195 | return ret; |
196 | }; | 196 | } |
197 | state->current_ci_flag = flag; | 197 | state->current_ci_flag = flag; |
198 | 198 | ||
199 | mutex_lock(&dev->gpio_lock); | 199 | mutex_lock(&dev->gpio_lock); |
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 39a4a4b9ed7e..5acdf954ff6b 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c | |||
@@ -542,11 +542,13 @@ struct cx23885_board cx23885_boards[] = { | |||
542 | { | 542 | { |
543 | .type = CX23885_VMUX_COMPOSITE1, | 543 | .type = CX23885_VMUX_COMPOSITE1, |
544 | .vmux = CX25840_COMPOSITE8, | 544 | .vmux = CX25840_COMPOSITE8, |
545 | .amux = CX25840_AUDIO7, | ||
545 | }, | 546 | }, |
546 | { | 547 | { |
547 | .type = CX23885_VMUX_SVIDEO, | 548 | .type = CX23885_VMUX_SVIDEO, |
548 | .vmux = CX25840_SVIDEO_LUMA3 | | 549 | .vmux = CX25840_SVIDEO_LUMA3 | |
549 | CX25840_SVIDEO_CHROMA4, | 550 | CX25840_SVIDEO_CHROMA4, |
551 | .amux = CX25840_AUDIO7, | ||
550 | }, | 552 | }, |
551 | { | 553 | { |
552 | .type = CX23885_VMUX_COMPONENT, | 554 | .type = CX23885_VMUX_COMPONENT, |
@@ -554,6 +556,7 @@ struct cx23885_board cx23885_boards[] = { | |||
554 | CX25840_VIN1_CH1 | | 556 | CX25840_VIN1_CH1 | |
555 | CX25840_VIN6_CH2 | | 557 | CX25840_VIN6_CH2 | |
556 | CX25840_VIN7_CH3, | 558 | CX25840_VIN7_CH3, |
559 | .amux = CX25840_AUDIO7, | ||
557 | }, | 560 | }, |
558 | }, | 561 | }, |
559 | }, | 562 | }, |
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index 8c4a9a5f9a50..1a21926ca412 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c | |||
@@ -508,7 +508,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
508 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) || | 508 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) || |
509 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || | 509 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || |
510 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || | 510 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || |
511 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) { | 511 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || |
512 | (dev->board == CX23885_BOARD_MYGICA_X8507)) { | ||
512 | /* Configure audio routing */ | 513 | /* Configure audio routing */ |
513 | v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, | 514 | v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, |
514 | INPUT(input)->amux, 0, 0); | 515 | INPUT(input)->amux, 0, 0); |
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c index c8c94fbf5d8d..d33fc1a23030 100644 --- a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c | |||
@@ -761,7 +761,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, | |||
761 | } | 761 | } |
762 | 762 | ||
763 | /* Default if filename is empty string */ | 763 | /* Default if filename is empty string */ |
764 | if (strcmp(dev->input_filename_ch2, "") == 0) { | 764 | if (strcmp(dev->_filename_ch2, "") == 0) { |
765 | if (dev->_isNTSC_ch2) { | 765 | if (dev->_isNTSC_ch2) { |
766 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == | 766 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == |
767 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : | 767 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : |
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c index 52c13e0b6492..6759fff8eb64 100644 --- a/drivers/media/pci/cx25821/cx25821-video-upstream.c +++ b/drivers/media/pci/cx25821/cx25821-video-upstream.c | |||
@@ -808,7 +808,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
808 | } | 808 | } |
809 | 809 | ||
810 | /* Default if filename is empty string */ | 810 | /* Default if filename is empty string */ |
811 | if (strcmp(dev->input_filename, "") == 0) { | 811 | if (strcmp(dev->_filename, "") == 0) { |
812 | if (dev->_isNTSC) { | 812 | if (dev->_isNTSC) { |
813 | dev->_filename = | 813 | dev->_filename = |
814 | (dev->_pixel_format == PIXEL_FRMT_411) ? | 814 | (dev->_pixel_format == PIXEL_FRMT_411) ? |
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index def363fb71c0..62184eb919e5 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c | |||
@@ -721,7 +721,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | |||
721 | 721 | ||
722 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 722 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
723 | f->fmt.pix.bytesperline = 0; | 723 | f->fmt.pix.bytesperline = 0; |
724 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; | 724 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ |
725 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 725 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
726 | f->fmt.pix.width = dev->width; | 726 | f->fmt.pix.width = dev->width; |
727 | f->fmt.pix.height = dev->height; | 727 | f->fmt.pix.height = dev->height; |
@@ -739,7 +739,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | |||
739 | 739 | ||
740 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 740 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
741 | f->fmt.pix.bytesperline = 0; | 741 | f->fmt.pix.bytesperline = 0; |
742 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; | 742 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ |
743 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 743 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
744 | dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", | 744 | dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", |
745 | dev->width, dev->height, fh->mpegq.field ); | 745 | dev->width, dev->height, fh->mpegq.field ); |
@@ -755,7 +755,7 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, | |||
755 | 755 | ||
756 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 756 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
757 | f->fmt.pix.bytesperline = 0; | 757 | f->fmt.pix.bytesperline = 0; |
758 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; | 758 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ |
759 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 759 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
760 | dev->width = f->fmt.pix.width; | 760 | dev->width = f->fmt.pix.width; |
761 | dev->height = f->fmt.pix.height; | 761 | dev->height = f->fmt.pix.height; |
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index d803bba09525..666f83b2f3c0 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c | |||
@@ -896,7 +896,7 @@ static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, | |||
896 | break; | 896 | break; |
897 | default: | 897 | default: |
898 | return -EINVAL; | 898 | return -EINVAL; |
899 | }; | 899 | } |
900 | 900 | ||
901 | return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; | 901 | return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; |
902 | } | 902 | } |
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index c04fb618e10b..d154bc197356 100644 --- a/drivers/media/pci/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c | |||
@@ -450,7 +450,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id) | |||
450 | cx88_core_irq(core,status); | 450 | cx88_core_irq(core,status); |
451 | if (status & PCI_INT_TSINT) | 451 | if (status & PCI_INT_TSINT) |
452 | cx8802_mpeg_irq(dev); | 452 | cx8802_mpeg_irq(dev); |
453 | }; | 453 | } |
454 | if (MAX_IRQ_LOOP == loop) { | 454 | if (MAX_IRQ_LOOP == loop) { |
455 | dprintk( 0, "clearing mask\n" ); | 455 | dprintk( 0, "clearing mask\n" ); |
456 | printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", | 456 | printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", |
diff --git a/drivers/media/pci/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c index 770ec05b5e9b..424fd97495dc 100644 --- a/drivers/media/pci/cx88/cx88-tvaudio.c +++ b/drivers/media/pci/cx88/cx88-tvaudio.c | |||
@@ -373,7 +373,7 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) | |||
373 | set_audio_registers(core, nicam_bgdki_common); | 373 | set_audio_registers(core, nicam_bgdki_common); |
374 | set_audio_registers(core, nicam_default); | 374 | set_audio_registers(core, nicam_default); |
375 | break; | 375 | break; |
376 | }; | 376 | } |
377 | 377 | ||
378 | mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS; | 378 | mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS; |
379 | set_audio_finish(core, mode); | 379 | set_audio_finish(core, mode); |
@@ -639,7 +639,7 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode) | |||
639 | dprintk("%s Warning: wrong value\n", __func__); | 639 | dprintk("%s Warning: wrong value\n", __func__); |
640 | return; | 640 | return; |
641 | break; | 641 | break; |
642 | }; | 642 | } |
643 | 643 | ||
644 | mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF; | 644 | mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF; |
645 | set_audio_finish(core, mode); | 645 | set_audio_finish(core, mode); |
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index a146d50d7795..05171457bf28 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c | |||
@@ -1535,7 +1535,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) | |||
1535 | cx88_core_irq(core,status); | 1535 | cx88_core_irq(core,status); |
1536 | if (status & PCI_INT_VIDINT) | 1536 | if (status & PCI_INT_VIDINT) |
1537 | cx8800_vid_irq(dev); | 1537 | cx8800_vid_irq(dev); |
1538 | }; | 1538 | } |
1539 | if (10 == loop) { | 1539 | if (10 == loop) { |
1540 | printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", | 1540 | printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", |
1541 | core->name); | 1541 | core->name); |
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 22f8758d047f..4a77124ee70e 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c | |||
@@ -1204,7 +1204,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str | |||
1204 | break; | 1204 | break; |
1205 | default: | 1205 | default: |
1206 | /* nothing */; | 1206 | /* nothing */; |
1207 | }; | 1207 | } |
1208 | switch (c->id) { | 1208 | switch (c->id) { |
1209 | case V4L2_CID_BRIGHTNESS: | 1209 | case V4L2_CID_BRIGHTNESS: |
1210 | dev->ctl_bright = c->value; | 1210 | dev->ctl_bright = c->value; |
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index f588d6296c76..181c7686e412 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
@@ -165,12 +165,12 @@ config VIDEO_SAMSUNG_S5P_JPEG | |||
165 | This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec | 165 | This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec |
166 | 166 | ||
167 | config VIDEO_SAMSUNG_S5P_MFC | 167 | config VIDEO_SAMSUNG_S5P_MFC |
168 | tristate "Samsung S5P MFC 5.1 Video Codec" | 168 | tristate "Samsung S5P MFC Video Codec" |
169 | depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P | 169 | depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P |
170 | select VIDEOBUF2_DMA_CONTIG | 170 | select VIDEOBUF2_DMA_CONTIG |
171 | default n | 171 | default n |
172 | help | 172 | help |
173 | MFC 5.1 driver for V4L2. | 173 | MFC 5.1 and 6.x driver for V4L2 |
174 | 174 | ||
175 | config VIDEO_MX2_EMMAPRP | 175 | config VIDEO_MX2_EMMAPRP |
176 | tristate "MX2 eMMa-PrP support" | 176 | tristate "MX2 eMMa-PrP support" |
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c index c4a82a1a8a97..69d7a58c92c3 100644 --- a/drivers/media/platform/davinci/vpbe.c +++ b/drivers/media/platform/davinci/vpbe.c | |||
@@ -174,26 +174,6 @@ static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev, | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev, | ||
178 | unsigned int dv_preset) | ||
179 | { | ||
180 | struct vpbe_config *cfg = vpbe_dev->cfg; | ||
181 | struct vpbe_enc_mode_info var; | ||
182 | int curr_output = vpbe_dev->current_out_index; | ||
183 | int i; | ||
184 | |||
185 | for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) { | ||
186 | var = cfg->outputs[curr_output].modes[i]; | ||
187 | if ((var.timings_type & VPBE_ENC_DV_PRESET) && | ||
188 | (var.timings.dv_preset == dv_preset)) { | ||
189 | vpbe_dev->current_timings = var; | ||
190 | return 0; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | /* Get std by std id */ | 177 | /* Get std by std id */ |
198 | static int vpbe_get_std_info(struct vpbe_device *vpbe_dev, | 178 | static int vpbe_get_std_info(struct vpbe_device *vpbe_dev, |
199 | v4l2_std_id std_id) | 179 | v4l2_std_id std_id) |
@@ -206,7 +186,7 @@ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev, | |||
206 | for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) { | 186 | for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) { |
207 | var = cfg->outputs[curr_output].modes[i]; | 187 | var = cfg->outputs[curr_output].modes[i]; |
208 | if ((var.timings_type & VPBE_ENC_STD) && | 188 | if ((var.timings_type & VPBE_ENC_STD) && |
209 | (var.timings.std_id & std_id)) { | 189 | (var.std_id & std_id)) { |
210 | vpbe_dev->current_timings = var; | 190 | vpbe_dev->current_timings = var; |
211 | return 0; | 191 | return 0; |
212 | } | 192 | } |
@@ -344,38 +324,42 @@ static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev) | |||
344 | } | 324 | } |
345 | 325 | ||
346 | /** | 326 | /** |
347 | * vpbe_s_dv_preset - Set the given preset timings in the encoder | 327 | * vpbe_s_dv_timings - Set the given preset timings in the encoder |
348 | * | 328 | * |
349 | * Sets the preset if supported by the current encoder. Return the status. | 329 | * Sets the timings if supported by the current encoder. Return the status. |
350 | * 0 - success & -EINVAL on error | 330 | * 0 - success & -EINVAL on error |
351 | */ | 331 | */ |
352 | static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev, | 332 | static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev, |
353 | struct v4l2_dv_preset *dv_preset) | 333 | struct v4l2_dv_timings *dv_timings) |
354 | { | 334 | { |
355 | struct vpbe_config *cfg = vpbe_dev->cfg; | 335 | struct vpbe_config *cfg = vpbe_dev->cfg; |
356 | int out_index = vpbe_dev->current_out_index; | 336 | int out_index = vpbe_dev->current_out_index; |
337 | struct vpbe_output *output = &cfg->outputs[out_index]; | ||
357 | int sd_index = vpbe_dev->current_sd_index; | 338 | int sd_index = vpbe_dev->current_sd_index; |
358 | int ret; | 339 | int ret, i; |
359 | 340 | ||
360 | 341 | ||
361 | if (!(cfg->outputs[out_index].output.capabilities & | 342 | if (!(cfg->outputs[out_index].output.capabilities & |
362 | V4L2_OUT_CAP_PRESETS)) | 343 | V4L2_OUT_CAP_DV_TIMINGS)) |
363 | return -EINVAL; | 344 | return -EINVAL; |
364 | 345 | ||
365 | ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset); | 346 | for (i = 0; i < output->num_modes; i++) { |
366 | 347 | if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS && | |
367 | if (ret) | 348 | !memcmp(&output->modes[i].dv_timings, |
368 | return ret; | 349 | dv_timings, sizeof(*dv_timings))) |
369 | 350 | break; | |
351 | } | ||
352 | if (i >= output->num_modes) | ||
353 | return -EINVAL; | ||
354 | vpbe_dev->current_timings = output->modes[i]; | ||
370 | mutex_lock(&vpbe_dev->lock); | 355 | mutex_lock(&vpbe_dev->lock); |
371 | 356 | ||
372 | |||
373 | ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video, | 357 | ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video, |
374 | s_dv_preset, dv_preset); | 358 | s_dv_timings, dv_timings); |
375 | if (!ret && (vpbe_dev->amp != NULL)) { | 359 | if (!ret && (vpbe_dev->amp != NULL)) { |
376 | /* Call amplifier subdevice */ | 360 | /* Call amplifier subdevice */ |
377 | ret = v4l2_subdev_call(vpbe_dev->amp, video, | 361 | ret = v4l2_subdev_call(vpbe_dev->amp, video, |
378 | s_dv_preset, dv_preset); | 362 | s_dv_timings, dv_timings); |
379 | } | 363 | } |
380 | /* set the lcd controller output for the given mode */ | 364 | /* set the lcd controller output for the given mode */ |
381 | if (!ret) { | 365 | if (!ret) { |
@@ -392,17 +376,17 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev, | |||
392 | } | 376 | } |
393 | 377 | ||
394 | /** | 378 | /** |
395 | * vpbe_g_dv_preset - Get the preset in the current encoder | 379 | * vpbe_g_dv_timings - Get the timings in the current encoder |
396 | * | 380 | * |
397 | * Get the preset in the current encoder. Return the status. 0 - success | 381 | * Get the timings in the current encoder. Return the status. 0 - success |
398 | * -EINVAL on error | 382 | * -EINVAL on error |
399 | */ | 383 | */ |
400 | static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev, | 384 | static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev, |
401 | struct v4l2_dv_preset *dv_preset) | 385 | struct v4l2_dv_timings *dv_timings) |
402 | { | 386 | { |
403 | if (vpbe_dev->current_timings.timings_type & | 387 | if (vpbe_dev->current_timings.timings_type & |
404 | VPBE_ENC_DV_PRESET) { | 388 | VPBE_ENC_CUSTOM_TIMINGS) { |
405 | dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset; | 389 | *dv_timings = vpbe_dev->current_timings.dv_timings; |
406 | return 0; | 390 | return 0; |
407 | } | 391 | } |
408 | 392 | ||
@@ -410,13 +394,13 @@ static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev, | |||
410 | } | 394 | } |
411 | 395 | ||
412 | /** | 396 | /** |
413 | * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder | 397 | * vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder |
414 | * | 398 | * |
415 | * Get the preset in the current encoder. Return the status. 0 - success | 399 | * Get the timings in the current encoder. Return the status. 0 - success |
416 | * -EINVAL on error | 400 | * -EINVAL on error |
417 | */ | 401 | */ |
418 | static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev, | 402 | static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev, |
419 | struct v4l2_dv_enum_preset *preset_info) | 403 | struct v4l2_enum_dv_timings *timings) |
420 | { | 404 | { |
421 | struct vpbe_config *cfg = vpbe_dev->cfg; | 405 | struct vpbe_config *cfg = vpbe_dev->cfg; |
422 | int out_index = vpbe_dev->current_out_index; | 406 | int out_index = vpbe_dev->current_out_index; |
@@ -424,12 +408,12 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev, | |||
424 | int j = 0; | 408 | int j = 0; |
425 | int i; | 409 | int i; |
426 | 410 | ||
427 | if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS)) | 411 | if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS)) |
428 | return -EINVAL; | 412 | return -EINVAL; |
429 | 413 | ||
430 | for (i = 0; i < output->num_modes; i++) { | 414 | for (i = 0; i < output->num_modes; i++) { |
431 | if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) { | 415 | if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) { |
432 | if (j == preset_info->index) | 416 | if (j == timings->index) |
433 | break; | 417 | break; |
434 | j++; | 418 | j++; |
435 | } | 419 | } |
@@ -437,9 +421,8 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev, | |||
437 | 421 | ||
438 | if (i == output->num_modes) | 422 | if (i == output->num_modes) |
439 | return -EINVAL; | 423 | return -EINVAL; |
440 | 424 | timings->timings = output->modes[i].dv_timings; | |
441 | return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset, | 425 | return 0; |
442 | preset_info); | ||
443 | } | 426 | } |
444 | 427 | ||
445 | /** | 428 | /** |
@@ -489,10 +472,10 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id) | |||
489 | */ | 472 | */ |
490 | static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id) | 473 | static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id) |
491 | { | 474 | { |
492 | struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings; | 475 | struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings; |
493 | 476 | ||
494 | if (cur_timings.timings_type & VPBE_ENC_STD) { | 477 | if (cur_timings->timings_type & VPBE_ENC_STD) { |
495 | *std_id = cur_timings.timings.std_id; | 478 | *std_id = cur_timings->std_id; |
496 | return 0; | 479 | return 0; |
497 | } | 480 | } |
498 | 481 | ||
@@ -511,7 +494,7 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev, | |||
511 | { | 494 | { |
512 | struct vpbe_enc_mode_info *preset_mode = NULL; | 495 | struct vpbe_enc_mode_info *preset_mode = NULL; |
513 | struct vpbe_config *cfg = vpbe_dev->cfg; | 496 | struct vpbe_config *cfg = vpbe_dev->cfg; |
514 | struct v4l2_dv_preset dv_preset; | 497 | struct v4l2_dv_timings dv_timings; |
515 | struct osd_state *osd_device; | 498 | struct osd_state *osd_device; |
516 | int out_index = vpbe_dev->current_out_index; | 499 | int out_index = vpbe_dev->current_out_index; |
517 | int ret = 0; | 500 | int ret = 0; |
@@ -530,11 +513,12 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev, | |||
530 | */ | 513 | */ |
531 | if (preset_mode->timings_type & VPBE_ENC_STD) | 514 | if (preset_mode->timings_type & VPBE_ENC_STD) |
532 | return vpbe_s_std(vpbe_dev, | 515 | return vpbe_s_std(vpbe_dev, |
533 | &preset_mode->timings.std_id); | 516 | &preset_mode->std_id); |
534 | if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) { | 517 | if (preset_mode->timings_type & |
535 | dv_preset.preset = | 518 | VPBE_ENC_CUSTOM_TIMINGS) { |
536 | preset_mode->timings.dv_preset; | 519 | dv_timings = |
537 | return vpbe_s_dv_preset(vpbe_dev, &dv_preset); | 520 | preset_mode->dv_timings; |
521 | return vpbe_s_dv_timings(vpbe_dev, &dv_timings); | ||
538 | } | 522 | } |
539 | } | 523 | } |
540 | } | 524 | } |
@@ -626,11 +610,11 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
626 | vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac"); | 610 | vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac"); |
627 | if (IS_ERR(vpbe_dev->dac_clk)) { | 611 | if (IS_ERR(vpbe_dev->dac_clk)) { |
628 | ret = PTR_ERR(vpbe_dev->dac_clk); | 612 | ret = PTR_ERR(vpbe_dev->dac_clk); |
629 | goto vpbe_unlock; | 613 | goto fail_mutex_unlock; |
630 | } | 614 | } |
631 | if (clk_enable(vpbe_dev->dac_clk)) { | 615 | if (clk_enable(vpbe_dev->dac_clk)) { |
632 | ret = -ENODEV; | 616 | ret = -ENODEV; |
633 | goto vpbe_unlock; | 617 | goto fail_mutex_unlock; |
634 | } | 618 | } |
635 | } | 619 | } |
636 | 620 | ||
@@ -642,7 +626,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
642 | if (ret) { | 626 | if (ret) { |
643 | v4l2_err(dev->driver, | 627 | v4l2_err(dev->driver, |
644 | "Unable to register v4l2 device.\n"); | 628 | "Unable to register v4l2 device.\n"); |
645 | goto vpbe_fail_clock; | 629 | goto fail_clk_put; |
646 | } | 630 | } |
647 | v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n"); | 631 | v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n"); |
648 | 632 | ||
@@ -658,7 +642,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
658 | v4l2_err(&vpbe_dev->v4l2_dev, | 642 | v4l2_err(&vpbe_dev->v4l2_dev, |
659 | "vpbe unable to init venc sub device\n"); | 643 | "vpbe unable to init venc sub device\n"); |
660 | ret = -ENODEV; | 644 | ret = -ENODEV; |
661 | goto vpbe_fail_v4l2_device; | 645 | goto fail_dev_unregister; |
662 | } | 646 | } |
663 | /* initialize osd device */ | 647 | /* initialize osd device */ |
664 | osd_device = vpbe_dev->osd_device; | 648 | osd_device = vpbe_dev->osd_device; |
@@ -669,7 +653,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
669 | v4l2_err(&vpbe_dev->v4l2_dev, | 653 | v4l2_err(&vpbe_dev->v4l2_dev, |
670 | "unable to initialize the OSD device"); | 654 | "unable to initialize the OSD device"); |
671 | err = -ENOMEM; | 655 | err = -ENOMEM; |
672 | goto vpbe_fail_v4l2_device; | 656 | goto fail_dev_unregister; |
673 | } | 657 | } |
674 | } | 658 | } |
675 | 659 | ||
@@ -685,7 +669,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
685 | v4l2_err(&vpbe_dev->v4l2_dev, | 669 | v4l2_err(&vpbe_dev->v4l2_dev, |
686 | "unable to allocate memory for encoders sub devices"); | 670 | "unable to allocate memory for encoders sub devices"); |
687 | ret = -ENOMEM; | 671 | ret = -ENOMEM; |
688 | goto vpbe_fail_v4l2_device; | 672 | goto fail_dev_unregister; |
689 | } | 673 | } |
690 | 674 | ||
691 | i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id); | 675 | 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) | |||
711 | " failed to register", | 695 | " failed to register", |
712 | enc_info->module_name); | 696 | enc_info->module_name); |
713 | ret = -ENODEV; | 697 | ret = -ENODEV; |
714 | goto vpbe_fail_sd_register; | 698 | goto fail_kfree_encoders; |
715 | } | 699 | } |
716 | } else | 700 | } else |
717 | v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders" | 701 | 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) | |||
730 | "amplifier %s failed to register", | 714 | "amplifier %s failed to register", |
731 | amp_info->module_name); | 715 | amp_info->module_name); |
732 | ret = -ENODEV; | 716 | ret = -ENODEV; |
733 | goto vpbe_fail_amp_register; | 717 | goto fail_kfree_encoders; |
734 | } | 718 | } |
735 | v4l2_info(&vpbe_dev->v4l2_dev, | 719 | v4l2_info(&vpbe_dev->v4l2_dev, |
736 | "v4l2 sub device %s registered\n", | 720 | "v4l2 sub device %s registered\n", |
@@ -770,16 +754,14 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
770 | /* TBD handling of bootargs for default output and mode */ | 754 | /* TBD handling of bootargs for default output and mode */ |
771 | return 0; | 755 | return 0; |
772 | 756 | ||
773 | vpbe_fail_amp_register: | 757 | fail_kfree_encoders: |
774 | kfree(vpbe_dev->amp); | ||
775 | vpbe_fail_sd_register: | ||
776 | kfree(vpbe_dev->encoders); | 758 | kfree(vpbe_dev->encoders); |
777 | vpbe_fail_v4l2_device: | 759 | fail_dev_unregister: |
778 | v4l2_device_unregister(&vpbe_dev->v4l2_dev); | 760 | v4l2_device_unregister(&vpbe_dev->v4l2_dev); |
779 | vpbe_fail_clock: | 761 | fail_clk_put: |
780 | if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) | 762 | if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) |
781 | clk_put(vpbe_dev->dac_clk); | 763 | clk_put(vpbe_dev->dac_clk); |
782 | vpbe_unlock: | 764 | fail_mutex_unlock: |
783 | mutex_unlock(&vpbe_dev->lock); | 765 | mutex_unlock(&vpbe_dev->lock); |
784 | return ret; | 766 | return ret; |
785 | } | 767 | } |
@@ -810,9 +792,9 @@ static struct vpbe_device_ops vpbe_dev_ops = { | |||
810 | .enum_outputs = vpbe_enum_outputs, | 792 | .enum_outputs = vpbe_enum_outputs, |
811 | .set_output = vpbe_set_output, | 793 | .set_output = vpbe_set_output, |
812 | .get_output = vpbe_get_output, | 794 | .get_output = vpbe_get_output, |
813 | .s_dv_preset = vpbe_s_dv_preset, | 795 | .s_dv_timings = vpbe_s_dv_timings, |
814 | .g_dv_preset = vpbe_g_dv_preset, | 796 | .g_dv_timings = vpbe_g_dv_timings, |
815 | .enum_dv_presets = vpbe_enum_dv_presets, | 797 | .enum_dv_timings = vpbe_enum_dv_timings, |
816 | .s_std = vpbe_s_std, | 798 | .s_std = vpbe_s_std, |
817 | .g_std = vpbe_g_std, | 799 | .g_std = vpbe_g_std, |
818 | .initialize = vpbe_initialize, | 800 | .initialize = vpbe_initialize, |
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 239f37bfa313..161c77650e2f 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c | |||
@@ -393,7 +393,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev, | |||
393 | int h_scale; | 393 | int h_scale; |
394 | int v_scale; | 394 | int v_scale; |
395 | 395 | ||
396 | v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id; | 396 | v4l2_std_id standard_id = vpbe_dev->current_timings.std_id; |
397 | 397 | ||
398 | /* | 398 | /* |
399 | * Application initially set the image format. Current display | 399 | * Application initially set the image format. Current display |
@@ -637,7 +637,7 @@ static int vpbe_display_s_crop(struct file *file, void *priv, | |||
637 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; | 637 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; |
638 | struct osd_layer_config *cfg = &layer->layer_info.config; | 638 | struct osd_layer_config *cfg = &layer->layer_info.config; |
639 | struct osd_state *osd_device = disp_dev->osd_device; | 639 | struct osd_state *osd_device = disp_dev->osd_device; |
640 | struct v4l2_rect *rect = &crop->c; | 640 | struct v4l2_rect rect = crop->c; |
641 | int ret; | 641 | int ret; |
642 | 642 | ||
643 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, | 643 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, |
@@ -648,21 +648,21 @@ static int vpbe_display_s_crop(struct file *file, void *priv, | |||
648 | return -EINVAL; | 648 | return -EINVAL; |
649 | } | 649 | } |
650 | 650 | ||
651 | if (rect->top < 0) | 651 | if (rect.top < 0) |
652 | rect->top = 0; | 652 | rect.top = 0; |
653 | if (rect->left < 0) | 653 | if (rect.left < 0) |
654 | rect->left = 0; | 654 | rect.left = 0; |
655 | 655 | ||
656 | vpbe_disp_check_window_params(disp_dev, rect); | 656 | vpbe_disp_check_window_params(disp_dev, &rect); |
657 | 657 | ||
658 | osd_device->ops.get_layer_config(osd_device, | 658 | osd_device->ops.get_layer_config(osd_device, |
659 | layer->layer_info.id, cfg); | 659 | layer->layer_info.id, cfg); |
660 | 660 | ||
661 | vpbe_disp_calculate_scale_factor(disp_dev, layer, | 661 | vpbe_disp_calculate_scale_factor(disp_dev, layer, |
662 | rect->width, | 662 | rect.width, |
663 | rect->height); | 663 | rect.height); |
664 | vpbe_disp_adj_position(disp_dev, layer, rect->top, | 664 | vpbe_disp_adj_position(disp_dev, layer, rect.top, |
665 | rect->left); | 665 | rect.left); |
666 | ret = osd_device->ops.set_layer_config(osd_device, | 666 | ret = osd_device->ops.set_layer_config(osd_device, |
667 | layer->layer_info.id, cfg); | 667 | layer->layer_info.id, cfg); |
668 | if (ret < 0) { | 668 | if (ret < 0) { |
@@ -943,7 +943,7 @@ static int vpbe_display_g_std(struct file *file, void *priv, | |||
943 | 943 | ||
944 | /* Get the standard from the current encoder */ | 944 | /* Get the standard from the current encoder */ |
945 | if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) { | 945 | if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) { |
946 | *std_id = vpbe_dev->current_timings.timings.std_id; | 946 | *std_id = vpbe_dev->current_timings.std_id; |
947 | return 0; | 947 | return 0; |
948 | } | 948 | } |
949 | 949 | ||
@@ -1029,29 +1029,29 @@ static int vpbe_display_g_output(struct file *file, void *priv, | |||
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | /** | 1031 | /** |
1032 | * vpbe_display_enum_dv_presets - Enumerate the dv presets | 1032 | * vpbe_display_enum_dv_timings - Enumerate the dv timings |
1033 | * | 1033 | * |
1034 | * enum the preset in the current encoder. Return the status. 0 - success | 1034 | * enum the timings in the current encoder. Return the status. 0 - success |
1035 | * -EINVAL on error | 1035 | * -EINVAL on error |
1036 | */ | 1036 | */ |
1037 | static int | 1037 | static int |
1038 | vpbe_display_enum_dv_presets(struct file *file, void *priv, | 1038 | vpbe_display_enum_dv_timings(struct file *file, void *priv, |
1039 | struct v4l2_dv_enum_preset *preset) | 1039 | struct v4l2_enum_dv_timings *timings) |
1040 | { | 1040 | { |
1041 | struct vpbe_fh *fh = priv; | 1041 | struct vpbe_fh *fh = priv; |
1042 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; | 1042 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; |
1043 | int ret; | 1043 | int ret; |
1044 | 1044 | ||
1045 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n"); | 1045 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n"); |
1046 | 1046 | ||
1047 | /* Enumerate outputs */ | 1047 | /* Enumerate outputs */ |
1048 | if (NULL == vpbe_dev->ops.enum_dv_presets) | 1048 | if (NULL == vpbe_dev->ops.enum_dv_timings) |
1049 | return -EINVAL; | 1049 | return -EINVAL; |
1050 | 1050 | ||
1051 | ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset); | 1051 | ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings); |
1052 | if (ret) { | 1052 | if (ret) { |
1053 | v4l2_err(&vpbe_dev->v4l2_dev, | 1053 | v4l2_err(&vpbe_dev->v4l2_dev, |
1054 | "Failed to enumerate dv presets info\n"); | 1054 | "Failed to enumerate dv timings info\n"); |
1055 | return -EINVAL; | 1055 | return -EINVAL; |
1056 | } | 1056 | } |
1057 | 1057 | ||
@@ -1059,21 +1059,21 @@ vpbe_display_enum_dv_presets(struct file *file, void *priv, | |||
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | /** | 1061 | /** |
1062 | * vpbe_display_s_dv_preset - Set the dv presets | 1062 | * vpbe_display_s_dv_timings - Set the dv timings |
1063 | * | 1063 | * |
1064 | * Set the preset in the current encoder. Return the status. 0 - success | 1064 | * Set the timings in the current encoder. Return the status. 0 - success |
1065 | * -EINVAL on error | 1065 | * -EINVAL on error |
1066 | */ | 1066 | */ |
1067 | static int | 1067 | static int |
1068 | vpbe_display_s_dv_preset(struct file *file, void *priv, | 1068 | vpbe_display_s_dv_timings(struct file *file, void *priv, |
1069 | struct v4l2_dv_preset *preset) | 1069 | struct v4l2_dv_timings *timings) |
1070 | { | 1070 | { |
1071 | struct vpbe_fh *fh = priv; | 1071 | struct vpbe_fh *fh = priv; |
1072 | struct vpbe_layer *layer = fh->layer; | 1072 | struct vpbe_layer *layer = fh->layer; |
1073 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; | 1073 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; |
1074 | int ret; | 1074 | int ret; |
1075 | 1075 | ||
1076 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n"); | 1076 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n"); |
1077 | 1077 | ||
1078 | 1078 | ||
1079 | /* If streaming is started, return error */ | 1079 | /* If streaming is started, return error */ |
@@ -1083,13 +1083,13 @@ vpbe_display_s_dv_preset(struct file *file, void *priv, | |||
1083 | } | 1083 | } |
1084 | 1084 | ||
1085 | /* Set the given standard in the encoder */ | 1085 | /* Set the given standard in the encoder */ |
1086 | if (!vpbe_dev->ops.s_dv_preset) | 1086 | if (!vpbe_dev->ops.s_dv_timings) |
1087 | return -EINVAL; | 1087 | return -EINVAL; |
1088 | 1088 | ||
1089 | ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset); | 1089 | ret = vpbe_dev->ops.s_dv_timings(vpbe_dev, timings); |
1090 | if (ret) { | 1090 | if (ret) { |
1091 | v4l2_err(&vpbe_dev->v4l2_dev, | 1091 | v4l2_err(&vpbe_dev->v4l2_dev, |
1092 | "Failed to set the dv presets info\n"); | 1092 | "Failed to set the dv timings info\n"); |
1093 | return -EINVAL; | 1093 | return -EINVAL; |
1094 | } | 1094 | } |
1095 | /* set the current norm to zero to be consistent. If STD is used | 1095 | /* 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, | |||
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | /** | 1103 | /** |
1104 | * vpbe_display_g_dv_preset - Set the dv presets | 1104 | * vpbe_display_g_dv_timings - Set the dv timings |
1105 | * | 1105 | * |
1106 | * Get the preset in the current encoder. Return the status. 0 - success | 1106 | * Get the timings in the current encoder. Return the status. 0 - success |
1107 | * -EINVAL on error | 1107 | * -EINVAL on error |
1108 | */ | 1108 | */ |
1109 | static int | 1109 | static int |
1110 | vpbe_display_g_dv_preset(struct file *file, void *priv, | 1110 | vpbe_display_g_dv_timings(struct file *file, void *priv, |
1111 | struct v4l2_dv_preset *dv_preset) | 1111 | struct v4l2_dv_timings *dv_timings) |
1112 | { | 1112 | { |
1113 | struct vpbe_fh *fh = priv; | 1113 | struct vpbe_fh *fh = priv; |
1114 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; | 1114 | struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; |
1115 | 1115 | ||
1116 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n"); | 1116 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n"); |
1117 | 1117 | ||
1118 | /* Get the given standard in the encoder */ | 1118 | /* Get the given standard in the encoder */ |
1119 | 1119 | ||
1120 | if (vpbe_dev->current_timings.timings_type & | 1120 | if (vpbe_dev->current_timings.timings_type & |
1121 | VPBE_ENC_DV_PRESET) { | 1121 | VPBE_ENC_CUSTOM_TIMINGS) { |
1122 | dv_preset->preset = | 1122 | *dv_timings = vpbe_dev->current_timings.dv_timings; |
1123 | vpbe_dev->current_timings.timings.dv_preset; | ||
1124 | } else { | 1123 | } else { |
1125 | return -EINVAL; | 1124 | return -EINVAL; |
1126 | } | 1125 | } |
@@ -1572,9 +1571,9 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { | |||
1572 | .vidioc_enum_output = vpbe_display_enum_output, | 1571 | .vidioc_enum_output = vpbe_display_enum_output, |
1573 | .vidioc_s_output = vpbe_display_s_output, | 1572 | .vidioc_s_output = vpbe_display_s_output, |
1574 | .vidioc_g_output = vpbe_display_g_output, | 1573 | .vidioc_g_output = vpbe_display_g_output, |
1575 | .vidioc_s_dv_preset = vpbe_display_s_dv_preset, | 1574 | .vidioc_s_dv_timings = vpbe_display_s_dv_timings, |
1576 | .vidioc_g_dv_preset = vpbe_display_g_dv_preset, | 1575 | .vidioc_g_dv_timings = vpbe_display_g_dv_timings, |
1577 | .vidioc_enum_dv_presets = vpbe_display_enum_dv_presets, | 1576 | .vidioc_enum_dv_timings = vpbe_display_enum_dv_timings, |
1578 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1577 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1579 | .vidioc_g_register = vpbe_display_g_register, | 1578 | .vidioc_g_register = vpbe_display_g_register, |
1580 | .vidioc_s_register = vpbe_display_s_register, | 1579 | .vidioc_s_register = vpbe_display_s_register, |
@@ -1639,8 +1638,7 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev, | |||
1639 | VPBE_ENC_STD) { | 1638 | VPBE_ENC_STD) { |
1640 | vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50); | 1639 | vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50); |
1641 | vbd->current_norm = | 1640 | vbd->current_norm = |
1642 | disp_dev->vpbe_dev-> | 1641 | disp_dev->vpbe_dev->current_timings.std_id; |
1643 | current_timings.timings.std_id; | ||
1644 | } else | 1642 | } else |
1645 | vbd->current_norm = 0; | 1643 | vbd->current_norm = 0; |
1646 | 1644 | ||
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 0302669622d6..aed7369b962a 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c | |||
@@ -298,7 +298,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd) | |||
298 | return -EINVAL; | 298 | return -EINVAL; |
299 | 299 | ||
300 | /* Setup clock at VPSS & VENC for SD */ | 300 | /* Setup clock at VPSS & VENC for SD */ |
301 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0) | 301 | if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0) |
302 | return -EINVAL; | 302 | return -EINVAL; |
303 | 303 | ||
304 | venc_enabledigitaloutput(sd, 0); | 304 | venc_enabledigitaloutput(sd, 0); |
@@ -345,7 +345,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd) | |||
345 | (pdata->venc_type != VPBE_VERSION_2)) | 345 | (pdata->venc_type != VPBE_VERSION_2)) |
346 | return -EINVAL; | 346 | return -EINVAL; |
347 | /* Setup clock at VPSS & VENC for SD */ | 347 | /* Setup clock at VPSS & VENC for SD */ |
348 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0) | 348 | if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0) |
349 | return -EINVAL; | 349 | return -EINVAL; |
350 | 350 | ||
351 | venc_enabledigitaloutput(sd, 0); | 351 | venc_enabledigitaloutput(sd, 0); |
@@ -385,7 +385,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd) | |||
385 | struct venc_state *venc = to_state(sd); | 385 | struct venc_state *venc = to_state(sd); |
386 | struct venc_platform_data *pdata = venc->pdata; | 386 | struct venc_platform_data *pdata = venc->pdata; |
387 | 387 | ||
388 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0) | 388 | if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0) |
389 | return -EINVAL; | 389 | return -EINVAL; |
390 | 390 | ||
391 | venc_enabledigitaloutput(sd, 0); | 391 | venc_enabledigitaloutput(sd, 0); |
@@ -413,7 +413,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd) | |||
413 | struct venc_state *venc = to_state(sd); | 413 | struct venc_state *venc = to_state(sd); |
414 | struct venc_platform_data *pdata = venc->pdata; | 414 | struct venc_platform_data *pdata = venc->pdata; |
415 | 415 | ||
416 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0) | 416 | if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0) |
417 | return -EINVAL; | 417 | return -EINVAL; |
418 | 418 | ||
419 | venc_enabledigitaloutput(sd, 0); | 419 | venc_enabledigitaloutput(sd, 0); |
@@ -446,26 +446,27 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) | |||
446 | return -EINVAL; | 446 | return -EINVAL; |
447 | } | 447 | } |
448 | 448 | ||
449 | static int venc_s_dv_preset(struct v4l2_subdev *sd, | 449 | static int venc_s_dv_timings(struct v4l2_subdev *sd, |
450 | struct v4l2_dv_preset *dv_preset) | 450 | struct v4l2_dv_timings *dv_timings) |
451 | { | 451 | { |
452 | struct venc_state *venc = to_state(sd); | 452 | struct venc_state *venc = to_state(sd); |
453 | u32 height = dv_timings->bt.height; | ||
453 | int ret; | 454 | int ret; |
454 | 455 | ||
455 | v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n"); | 456 | v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n"); |
456 | 457 | ||
457 | if (dv_preset->preset == V4L2_DV_576P50) | 458 | if (height == 576) |
458 | return venc_set_576p50(sd); | 459 | return venc_set_576p50(sd); |
459 | else if (dv_preset->preset == V4L2_DV_480P59_94) | 460 | else if (height == 480) |
460 | return venc_set_480p59_94(sd); | 461 | return venc_set_480p59_94(sd); |
461 | else if ((dv_preset->preset == V4L2_DV_720P60) && | 462 | else if ((height == 720) && |
462 | (venc->pdata->venc_type == VPBE_VERSION_2)) { | 463 | (venc->pdata->venc_type == VPBE_VERSION_2)) { |
463 | /* TBD setup internal 720p mode here */ | 464 | /* TBD setup internal 720p mode here */ |
464 | ret = venc_set_720p60_internal(sd); | 465 | ret = venc_set_720p60_internal(sd); |
465 | /* for DM365 VPBE, there is DAC inside */ | 466 | /* for DM365 VPBE, there is DAC inside */ |
466 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | 467 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); |
467 | return ret; | 468 | return ret; |
468 | } else if ((dv_preset->preset == V4L2_DV_1080I30) && | 469 | } else if ((height == 1080) && |
469 | (venc->pdata->venc_type == VPBE_VERSION_2)) { | 470 | (venc->pdata->venc_type == VPBE_VERSION_2)) { |
470 | /* TBD setup internal 1080i mode here */ | 471 | /* TBD setup internal 1080i mode here */ |
471 | ret = venc_set_1080i30_internal(sd); | 472 | ret = venc_set_1080i30_internal(sd); |
@@ -518,7 +519,7 @@ static const struct v4l2_subdev_core_ops venc_core_ops = { | |||
518 | static const struct v4l2_subdev_video_ops venc_video_ops = { | 519 | static const struct v4l2_subdev_video_ops venc_video_ops = { |
519 | .s_routing = venc_s_routing, | 520 | .s_routing = venc_s_routing, |
520 | .s_std_output = venc_s_std_output, | 521 | .s_std_output = venc_s_std_output, |
521 | .s_dv_preset = venc_s_dv_preset, | 522 | .s_dv_timings = venc_s_dv_timings, |
522 | }; | 523 | }; |
523 | 524 | ||
524 | static const struct v4l2_subdev_ops venc_ops = { | 525 | static const struct v4l2_subdev_ops venc_ops = { |
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 48052cbffc2b..8be492cd8ed4 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c | |||
@@ -1669,6 +1669,7 @@ static int vpfe_s_crop(struct file *file, void *priv, | |||
1669 | const struct v4l2_crop *crop) | 1669 | const struct v4l2_crop *crop) |
1670 | { | 1670 | { |
1671 | struct vpfe_device *vpfe_dev = video_drvdata(file); | 1671 | struct vpfe_device *vpfe_dev = video_drvdata(file); |
1672 | struct v4l2_rect rect = crop->c; | ||
1672 | int ret = 0; | 1673 | int ret = 0; |
1673 | 1674 | ||
1674 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n"); | 1675 | 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, | |||
1684 | if (ret) | 1685 | if (ret) |
1685 | return ret; | 1686 | return ret; |
1686 | 1687 | ||
1687 | if (crop->c.top < 0 || crop->c.left < 0) { | 1688 | if (rect.top < 0 || rect.left < 0) { |
1688 | v4l2_err(&vpfe_dev->v4l2_dev, | 1689 | v4l2_err(&vpfe_dev->v4l2_dev, |
1689 | "doesn't support negative values for top & left\n"); | 1690 | "doesn't support negative values for top & left\n"); |
1690 | ret = -EINVAL; | 1691 | ret = -EINVAL; |
@@ -1692,26 +1693,26 @@ static int vpfe_s_crop(struct file *file, void *priv, | |||
1692 | } | 1693 | } |
1693 | 1694 | ||
1694 | /* adjust the width to 16 pixel boundary */ | 1695 | /* adjust the width to 16 pixel boundary */ |
1695 | crop->c.width = ((crop->c.width + 15) & ~0xf); | 1696 | rect.width = ((rect.width + 15) & ~0xf); |
1696 | 1697 | ||
1697 | /* make sure parameters are valid */ | 1698 | /* make sure parameters are valid */ |
1698 | if ((crop->c.left + crop->c.width > | 1699 | if ((rect.left + rect.width > |
1699 | vpfe_dev->std_info.active_pixels) || | 1700 | vpfe_dev->std_info.active_pixels) || |
1700 | (crop->c.top + crop->c.height > | 1701 | (rect.top + rect.height > |
1701 | vpfe_dev->std_info.active_lines)) { | 1702 | vpfe_dev->std_info.active_lines)) { |
1702 | v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n"); | 1703 | v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n"); |
1703 | ret = -EINVAL; | 1704 | ret = -EINVAL; |
1704 | goto unlock_out; | 1705 | goto unlock_out; |
1705 | } | 1706 | } |
1706 | ccdc_dev->hw_ops.set_image_window(&crop->c); | 1707 | ccdc_dev->hw_ops.set_image_window(&rect); |
1707 | vpfe_dev->fmt.fmt.pix.width = crop->c.width; | 1708 | vpfe_dev->fmt.fmt.pix.width = rect.width; |
1708 | vpfe_dev->fmt.fmt.pix.height = crop->c.height; | 1709 | vpfe_dev->fmt.fmt.pix.height = rect.height; |
1709 | vpfe_dev->fmt.fmt.pix.bytesperline = | 1710 | vpfe_dev->fmt.fmt.pix.bytesperline = |
1710 | ccdc_dev->hw_ops.get_line_length(); | 1711 | ccdc_dev->hw_ops.get_line_length(); |
1711 | vpfe_dev->fmt.fmt.pix.sizeimage = | 1712 | vpfe_dev->fmt.fmt.pix.sizeimage = |
1712 | vpfe_dev->fmt.fmt.pix.bytesperline * | 1713 | vpfe_dev->fmt.fmt.pix.bytesperline * |
1713 | vpfe_dev->fmt.fmt.pix.height; | 1714 | vpfe_dev->fmt.fmt.pix.height; |
1714 | vpfe_dev->crop = crop->c; | 1715 | vpfe_dev->crop = rect; |
1715 | unlock_out: | 1716 | unlock_out: |
1716 | mutex_unlock(&vpfe_dev->lock); | 1717 | mutex_unlock(&vpfe_dev->lock); |
1717 | return ret; | 1718 | return ret; |
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 0bafecac4923..fcabc023885d 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c | |||
@@ -311,12 +311,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
311 | } | 311 | } |
312 | 312 | ||
313 | /* configure 1 or 2 channel mode */ | 313 | /* configure 1 or 2 channel mode */ |
314 | ret = vpif_config_data->setup_input_channel_mode | 314 | if (vpif_config_data->setup_input_channel_mode) { |
315 | (vpif->std_info.ycmux_mode); | 315 | ret = vpif_config_data-> |
316 | 316 | setup_input_channel_mode(vpif->std_info.ycmux_mode); | |
317 | if (ret < 0) { | 317 | if (ret < 0) { |
318 | vpif_dbg(1, debug, "can't set vpif channel mode\n"); | 318 | vpif_dbg(1, debug, "can't set vpif channel mode\n"); |
319 | return ret; | 319 | return ret; |
320 | } | ||
320 | } | 321 | } |
321 | 322 | ||
322 | /* Call vpif_set_params function to set the parameters and addresses */ | 323 | /* 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) | |||
863 | */ | 864 | */ |
864 | static int vpif_open(struct file *filep) | 865 | static int vpif_open(struct file *filep) |
865 | { | 866 | { |
866 | struct vpif_capture_config *config = vpif_dev->platform_data; | ||
867 | struct video_device *vdev = video_devdata(filep); | 867 | struct video_device *vdev = video_devdata(filep); |
868 | struct common_obj *common; | 868 | struct common_obj *common; |
869 | struct video_obj *vid_ch; | 869 | struct video_obj *vid_ch; |
870 | struct channel_obj *ch; | 870 | struct channel_obj *ch; |
871 | struct vpif_fh *fh; | 871 | struct vpif_fh *fh; |
872 | int i; | ||
873 | 872 | ||
874 | vpif_dbg(2, debug, "vpif_open\n"); | 873 | vpif_dbg(2, debug, "vpif_open\n"); |
875 | 874 | ||
@@ -878,26 +877,6 @@ static int vpif_open(struct file *filep) | |||
878 | vid_ch = &ch->video; | 877 | vid_ch = &ch->video; |
879 | common = &ch->common[VPIF_VIDEO_INDEX]; | 878 | common = &ch->common[VPIF_VIDEO_INDEX]; |
880 | 879 | ||
881 | if (NULL == ch->curr_subdev_info) { | ||
882 | /** | ||
883 | * search through the sub device to see a registered | ||
884 | * sub device and make it as current sub device | ||
885 | */ | ||
886 | for (i = 0; i < config->subdev_count; i++) { | ||
887 | if (vpif_obj.sd[i]) { | ||
888 | /* the sub device is registered */ | ||
889 | ch->curr_subdev_info = &config->subdev_info[i]; | ||
890 | /* make first input as the current input */ | ||
891 | vid_ch->input_idx = 0; | ||
892 | break; | ||
893 | } | ||
894 | } | ||
895 | if (i == config->subdev_count) { | ||
896 | vpif_err("No sub device registered\n"); | ||
897 | return -ENOENT; | ||
898 | } | ||
899 | } | ||
900 | |||
901 | /* Allocate memory for the file handle object */ | 880 | /* Allocate memory for the file handle object */ |
902 | fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); | 881 | fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); |
903 | if (NULL == fh) { | 882 | if (NULL == fh) { |
@@ -997,6 +976,7 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
997 | struct common_obj *common; | 976 | struct common_obj *common; |
998 | u8 index = 0; | 977 | u8 index = 0; |
999 | struct vb2_queue *q; | 978 | struct vb2_queue *q; |
979 | int ret; | ||
1000 | 980 | ||
1001 | vpif_dbg(2, debug, "vpif_reqbufs\n"); | 981 | vpif_dbg(2, debug, "vpif_reqbufs\n"); |
1002 | 982 | ||
@@ -1036,8 +1016,12 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
1036 | q->mem_ops = &vb2_dma_contig_memops; | 1016 | q->mem_ops = &vb2_dma_contig_memops; |
1037 | q->buf_struct_size = sizeof(struct vpif_cap_buffer); | 1017 | q->buf_struct_size = sizeof(struct vpif_cap_buffer); |
1038 | 1018 | ||
1039 | vb2_queue_init(q); | 1019 | ret = vb2_queue_init(q); |
1040 | 1020 | if (ret) { | |
1021 | vpif_err("vpif_capture: vb2_queue_init() failed\n"); | ||
1022 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | ||
1023 | return ret; | ||
1024 | } | ||
1041 | /* Set io allowed member of file handle to TRUE */ | 1025 | /* Set io allowed member of file handle to TRUE */ |
1042 | fh->io_allowed[index] = 1; | 1026 | fh->io_allowed[index] = 1; |
1043 | /* Increment io usrs member of channel object to 1 */ | 1027 | /* Increment io usrs member of channel object to 1 */ |
@@ -1175,10 +1159,9 @@ static int vpif_streamon(struct file *file, void *priv, | |||
1175 | return ret; | 1159 | return ret; |
1176 | 1160 | ||
1177 | /* Enable streamon on the sub device */ | 1161 | /* Enable streamon on the sub device */ |
1178 | ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, | 1162 | ret = v4l2_subdev_call(ch->sd, video, s_stream, 1); |
1179 | s_stream, 1); | ||
1180 | 1163 | ||
1181 | if (ret && (ret != -ENOIOCTLCMD)) { | 1164 | if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { |
1182 | vpif_dbg(1, debug, "stream on failed in subdev\n"); | 1165 | vpif_dbg(1, debug, "stream on failed in subdev\n"); |
1183 | return ret; | 1166 | return ret; |
1184 | } | 1167 | } |
@@ -1238,73 +1221,105 @@ static int vpif_streamoff(struct file *file, void *priv, | |||
1238 | 1221 | ||
1239 | common->started = 0; | 1222 | common->started = 0; |
1240 | 1223 | ||
1241 | ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, | 1224 | ret = v4l2_subdev_call(ch->sd, video, s_stream, 0); |
1242 | s_stream, 0); | ||
1243 | 1225 | ||
1244 | if (ret && (ret != -ENOIOCTLCMD)) | 1226 | if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) |
1245 | vpif_dbg(1, debug, "stream off failed in subdev\n"); | 1227 | vpif_dbg(1, debug, "stream off failed in subdev\n"); |
1246 | 1228 | ||
1247 | return vb2_streamoff(&common->buffer_queue, buftype); | 1229 | return vb2_streamoff(&common->buffer_queue, buftype); |
1248 | } | 1230 | } |
1249 | 1231 | ||
1250 | /** | 1232 | /** |
1251 | * vpif_map_sub_device_to_input() - Maps sub device to input | 1233 | * vpif_input_to_subdev() - Maps input to sub device |
1252 | * @ch - ptr to channel | 1234 | * @vpif_cfg - global config ptr |
1253 | * @config - ptr to capture configuration | 1235 | * @chan_cfg - channel config ptr |
1254 | * @input_index - Given input index from application | 1236 | * @input_index - Given input index from application |
1255 | * @sub_device_index - index into sd table | ||
1256 | * | 1237 | * |
1257 | * lookup the sub device information for a given input index. | 1238 | * lookup the sub device information for a given input index. |
1258 | * we report all the inputs to application. inputs table also | 1239 | * we report all the inputs to application. inputs table also |
1259 | * has sub device name for the each input | 1240 | * has sub device name for the each input |
1260 | */ | 1241 | */ |
1261 | static struct vpif_subdev_info *vpif_map_sub_device_to_input( | 1242 | static int vpif_input_to_subdev( |
1262 | struct channel_obj *ch, | 1243 | struct vpif_capture_config *vpif_cfg, |
1263 | struct vpif_capture_config *vpif_cfg, | 1244 | struct vpif_capture_chan_config *chan_cfg, |
1264 | int input_index, | 1245 | int input_index) |
1265 | int *sub_device_index) | ||
1266 | { | 1246 | { |
1267 | struct vpif_capture_chan_config *chan_cfg; | 1247 | struct vpif_subdev_info *subdev_info; |
1268 | struct vpif_subdev_info *subdev_info = NULL; | 1248 | const char *subdev_name; |
1269 | const char *subdev_name = NULL; | ||
1270 | int i; | 1249 | int i; |
1271 | 1250 | ||
1272 | vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n"); | 1251 | vpif_dbg(2, debug, "vpif_input_to_subdev\n"); |
1273 | 1252 | ||
1274 | chan_cfg = &vpif_cfg->chan_config[ch->channel_id]; | 1253 | subdev_name = chan_cfg->inputs[input_index].subdev_name; |
1275 | 1254 | if (subdev_name == NULL) | |
1276 | /** | 1255 | return -1; |
1277 | * search through the inputs to find the sub device supporting | ||
1278 | * the input | ||
1279 | */ | ||
1280 | for (i = 0; i < chan_cfg->input_count; i++) { | ||
1281 | /* For each sub device, loop through input */ | ||
1282 | if (i == input_index) { | ||
1283 | subdev_name = chan_cfg->inputs[i].subdev_name; | ||
1284 | break; | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | /* if reached maximum. return null */ | ||
1289 | if (i == chan_cfg->input_count || (NULL == subdev_name)) | ||
1290 | return subdev_info; | ||
1291 | 1256 | ||
1292 | /* loop through the sub device list to get the sub device info */ | 1257 | /* loop through the sub device list to get the sub device info */ |
1293 | for (i = 0; i < vpif_cfg->subdev_count; i++) { | 1258 | for (i = 0; i < vpif_cfg->subdev_count; i++) { |
1294 | subdev_info = &vpif_cfg->subdev_info[i]; | 1259 | subdev_info = &vpif_cfg->subdev_info[i]; |
1295 | if (!strcmp(subdev_info->name, subdev_name)) | 1260 | if (!strcmp(subdev_info->name, subdev_name)) |
1296 | break; | 1261 | return i; |
1262 | } | ||
1263 | return -1; | ||
1264 | } | ||
1265 | |||
1266 | /** | ||
1267 | * vpif_set_input() - Select an input | ||
1268 | * @vpif_cfg - global config ptr | ||
1269 | * @ch - channel | ||
1270 | * @_index - Given input index from application | ||
1271 | * | ||
1272 | * Select the given input. | ||
1273 | */ | ||
1274 | static int vpif_set_input( | ||
1275 | struct vpif_capture_config *vpif_cfg, | ||
1276 | struct channel_obj *ch, | ||
1277 | int index) | ||
1278 | { | ||
1279 | struct vpif_capture_chan_config *chan_cfg = | ||
1280 | &vpif_cfg->chan_config[ch->channel_id]; | ||
1281 | struct vpif_subdev_info *subdev_info = NULL; | ||
1282 | struct v4l2_subdev *sd = NULL; | ||
1283 | u32 input = 0, output = 0; | ||
1284 | int sd_index; | ||
1285 | int ret; | ||
1286 | |||
1287 | sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index); | ||
1288 | if (sd_index >= 0) { | ||
1289 | sd = vpif_obj.sd[sd_index]; | ||
1290 | subdev_info = &vpif_cfg->subdev_info[sd_index]; | ||
1297 | } | 1291 | } |
1298 | 1292 | ||
1299 | if (i == vpif_cfg->subdev_count) | 1293 | /* first setup input path from sub device to vpif */ |
1300 | return subdev_info; | 1294 | if (sd && vpif_cfg->setup_input_path) { |
1295 | ret = vpif_cfg->setup_input_path(ch->channel_id, | ||
1296 | subdev_info->name); | ||
1297 | if (ret < 0) { | ||
1298 | vpif_dbg(1, debug, "couldn't setup input path for the" \ | ||
1299 | " sub device %s, for input index %d\n", | ||
1300 | subdev_info->name, index); | ||
1301 | return ret; | ||
1302 | } | ||
1303 | } | ||
1301 | 1304 | ||
1302 | /* check if the sub device is registered */ | 1305 | if (sd) { |
1303 | if (NULL == vpif_obj.sd[i]) | 1306 | input = chan_cfg->inputs[index].input_route; |
1304 | return NULL; | 1307 | output = chan_cfg->inputs[index].output_route; |
1308 | ret = v4l2_subdev_call(sd, video, s_routing, | ||
1309 | input, output, 0); | ||
1310 | if (ret < 0 && ret != -ENOIOCTLCMD) { | ||
1311 | vpif_dbg(1, debug, "Failed to set input\n"); | ||
1312 | return ret; | ||
1313 | } | ||
1314 | } | ||
1315 | ch->input_idx = index; | ||
1316 | ch->sd = sd; | ||
1317 | /* copy interface parameters to vpif */ | ||
1318 | ch->vpifparams.iface = chan_cfg->vpif_if; | ||
1305 | 1319 | ||
1306 | *sub_device_index = i; | 1320 | /* update tvnorms from the sub device input info */ |
1307 | return subdev_info; | 1321 | ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; |
1322 | return 0; | ||
1308 | } | 1323 | } |
1309 | 1324 | ||
1310 | /** | 1325 | /** |
@@ -1324,12 +1339,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) | |||
1324 | vpif_dbg(2, debug, "vpif_querystd\n"); | 1339 | vpif_dbg(2, debug, "vpif_querystd\n"); |
1325 | 1340 | ||
1326 | /* Call querystd function of decoder device */ | 1341 | /* Call querystd function of decoder device */ |
1327 | ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, | 1342 | ret = v4l2_subdev_call(ch->sd, video, querystd, std_id); |
1328 | querystd, std_id); | ||
1329 | if (ret < 0) | ||
1330 | vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); | ||
1331 | 1343 | ||
1332 | return ret; | 1344 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
1345 | return -ENODATA; | ||
1346 | if (ret) { | ||
1347 | vpif_dbg(1, debug, "Failed to query standard for sub devices\n"); | ||
1348 | return ret; | ||
1349 | } | ||
1350 | |||
1351 | return 0; | ||
1333 | } | 1352 | } |
1334 | 1353 | ||
1335 | /** | 1354 | /** |
@@ -1397,11 +1416,12 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) | |||
1397 | vpif_config_format(ch); | 1416 | vpif_config_format(ch); |
1398 | 1417 | ||
1399 | /* set standard in the sub device */ | 1418 | /* set standard in the sub device */ |
1400 | ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, | 1419 | ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id); |
1401 | s_std, *std_id); | 1420 | if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { |
1402 | if (ret < 0) | ||
1403 | vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); | 1421 | vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); |
1404 | return ret; | 1422 | return ret; |
1423 | } | ||
1424 | return 0; | ||
1405 | } | 1425 | } |
1406 | 1426 | ||
1407 | /** | 1427 | /** |
@@ -1441,10 +1461,8 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index) | |||
1441 | { | 1461 | { |
1442 | struct vpif_fh *fh = priv; | 1462 | struct vpif_fh *fh = priv; |
1443 | struct channel_obj *ch = fh->channel; | 1463 | struct channel_obj *ch = fh->channel; |
1444 | struct video_obj *vid_ch = &ch->video; | ||
1445 | |||
1446 | *index = vid_ch->input_idx; | ||
1447 | 1464 | ||
1465 | *index = ch->input_idx; | ||
1448 | return 0; | 1466 | return 0; |
1449 | } | 1467 | } |
1450 | 1468 | ||
@@ -1461,13 +1479,13 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) | |||
1461 | struct vpif_fh *fh = priv; | 1479 | struct vpif_fh *fh = priv; |
1462 | struct channel_obj *ch = fh->channel; | 1480 | struct channel_obj *ch = fh->channel; |
1463 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 1481 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
1464 | struct video_obj *vid_ch = &ch->video; | 1482 | int ret; |
1465 | struct vpif_subdev_info *subdev_info; | ||
1466 | int ret = 0, sd_index = 0; | ||
1467 | u32 input = 0, output = 0; | ||
1468 | 1483 | ||
1469 | chan_cfg = &config->chan_config[ch->channel_id]; | 1484 | chan_cfg = &config->chan_config[ch->channel_id]; |
1470 | 1485 | ||
1486 | if (index >= chan_cfg->input_count) | ||
1487 | return -EINVAL; | ||
1488 | |||
1471 | if (common->started) { | 1489 | if (common->started) { |
1472 | vpif_err("Streaming in progress\n"); | 1490 | vpif_err("Streaming in progress\n"); |
1473 | return -EBUSY; | 1491 | return -EBUSY; |
@@ -1486,45 +1504,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) | |||
1486 | return ret; | 1504 | return ret; |
1487 | 1505 | ||
1488 | fh->initialized = 1; | 1506 | fh->initialized = 1; |
1489 | subdev_info = vpif_map_sub_device_to_input(ch, config, index, | 1507 | return vpif_set_input(config, ch, index); |
1490 | &sd_index); | ||
1491 | if (NULL == subdev_info) { | ||
1492 | vpif_dbg(1, debug, | ||
1493 | "couldn't lookup sub device for the input index\n"); | ||
1494 | return -EINVAL; | ||
1495 | } | ||
1496 | |||
1497 | /* first setup input path from sub device to vpif */ | ||
1498 | if (config->setup_input_path) { | ||
1499 | ret = config->setup_input_path(ch->channel_id, | ||
1500 | subdev_info->name); | ||
1501 | if (ret < 0) { | ||
1502 | vpif_dbg(1, debug, "couldn't setup input path for the" | ||
1503 | " sub device %s, for input index %d\n", | ||
1504 | subdev_info->name, index); | ||
1505 | return ret; | ||
1506 | } | ||
1507 | } | ||
1508 | |||
1509 | if (subdev_info->can_route) { | ||
1510 | input = subdev_info->input; | ||
1511 | output = subdev_info->output; | ||
1512 | ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing, | ||
1513 | input, output, 0); | ||
1514 | if (ret < 0) { | ||
1515 | vpif_dbg(1, debug, "Failed to set input\n"); | ||
1516 | return ret; | ||
1517 | } | ||
1518 | } | ||
1519 | vid_ch->input_idx = index; | ||
1520 | ch->curr_subdev_info = subdev_info; | ||
1521 | ch->curr_sd_index = sd_index; | ||
1522 | /* copy interface parameters to vpif */ | ||
1523 | ch->vpifparams.iface = subdev_info->vpif_if; | ||
1524 | |||
1525 | /* update tvnorms from the sub device input info */ | ||
1526 | ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; | ||
1527 | return ret; | ||
1528 | } | 1508 | } |
1529 | 1509 | ||
1530 | /** | 1510 | /** |
@@ -1655,9 +1635,11 @@ static int vpif_querycap(struct file *file, void *priv, | |||
1655 | { | 1635 | { |
1656 | struct vpif_capture_config *config = vpif_dev->platform_data; | 1636 | struct vpif_capture_config *config = vpif_dev->platform_data; |
1657 | 1637 | ||
1658 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | 1638 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; |
1659 | strlcpy(cap->driver, "vpif capture", sizeof(cap->driver)); | 1639 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
1660 | strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info)); | 1640 | snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); |
1641 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", | ||
1642 | dev_name(vpif_dev)); | ||
1661 | strlcpy(cap->card, config->card_name, sizeof(cap->card)); | 1643 | strlcpy(cap->card, config->card_name, sizeof(cap->card)); |
1662 | 1644 | ||
1663 | return 0; | 1645 | return 0; |
@@ -1730,9 +1712,12 @@ vpif_enum_dv_timings(struct file *file, void *priv, | |||
1730 | { | 1712 | { |
1731 | struct vpif_fh *fh = priv; | 1713 | struct vpif_fh *fh = priv; |
1732 | struct channel_obj *ch = fh->channel; | 1714 | struct channel_obj *ch = fh->channel; |
1715 | int ret; | ||
1733 | 1716 | ||
1734 | return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], | 1717 | ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); |
1735 | video, enum_dv_timings, timings); | 1718 | if (ret == -ENOIOCTLCMD && ret == -ENODEV) |
1719 | return -EINVAL; | ||
1720 | return ret; | ||
1736 | } | 1721 | } |
1737 | 1722 | ||
1738 | /** | 1723 | /** |
@@ -1747,9 +1732,12 @@ vpif_query_dv_timings(struct file *file, void *priv, | |||
1747 | { | 1732 | { |
1748 | struct vpif_fh *fh = priv; | 1733 | struct vpif_fh *fh = priv; |
1749 | struct channel_obj *ch = fh->channel; | 1734 | struct channel_obj *ch = fh->channel; |
1735 | int ret; | ||
1750 | 1736 | ||
1751 | return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], | 1737 | ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings); |
1752 | video, query_dv_timings, timings); | 1738 | if (ret == -ENOIOCTLCMD && ret == -ENODEV) |
1739 | return -ENODATA; | ||
1740 | return ret; | ||
1753 | } | 1741 | } |
1754 | 1742 | ||
1755 | /** | 1743 | /** |
@@ -1775,13 +1763,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
1775 | } | 1763 | } |
1776 | 1764 | ||
1777 | /* Configure subdevice timings, if any */ | 1765 | /* Configure subdevice timings, if any */ |
1778 | ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], | 1766 | ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); |
1779 | video, s_dv_timings, timings); | 1767 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
1780 | if (ret == -ENOIOCTLCMD) { | 1768 | ret = 0; |
1781 | vpif_dbg(2, debug, "Custom DV timings not supported by " | ||
1782 | "subdevice\n"); | ||
1783 | return -EINVAL; | ||
1784 | } | ||
1785 | if (ret < 0) { | 1769 | if (ret < 0) { |
1786 | vpif_dbg(2, debug, "Error setting custom DV timings\n"); | 1770 | vpif_dbg(2, debug, "Error setting custom DV timings\n"); |
1787 | return ret; | 1771 | return ret; |
@@ -1906,8 +1890,7 @@ static int vpif_dbg_g_register(struct file *file, void *priv, | |||
1906 | struct vpif_fh *fh = priv; | 1890 | struct vpif_fh *fh = priv; |
1907 | struct channel_obj *ch = fh->channel; | 1891 | struct channel_obj *ch = fh->channel; |
1908 | 1892 | ||
1909 | return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, | 1893 | return v4l2_subdev_call(ch->sd, core, g_register, reg); |
1910 | g_register, reg); | ||
1911 | } | 1894 | } |
1912 | 1895 | ||
1913 | /* | 1896 | /* |
@@ -1924,8 +1907,7 @@ static int vpif_dbg_s_register(struct file *file, void *priv, | |||
1924 | struct vpif_fh *fh = priv; | 1907 | struct vpif_fh *fh = priv; |
1925 | struct channel_obj *ch = fh->channel; | 1908 | struct channel_obj *ch = fh->channel; |
1926 | 1909 | ||
1927 | return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, | 1910 | return v4l2_subdev_call(ch->sd, core, s_register, reg); |
1928 | s_register, reg); | ||
1929 | } | 1911 | } |
1930 | #endif | 1912 | #endif |
1931 | 1913 | ||
@@ -2063,7 +2045,8 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2063 | { | 2045 | { |
2064 | struct vpif_subdev_info *subdevdata; | 2046 | struct vpif_subdev_info *subdevdata; |
2065 | struct vpif_capture_config *config; | 2047 | struct vpif_capture_config *config; |
2066 | int i, j, k, m, q, err; | 2048 | int i, j, k, err; |
2049 | int res_idx = 0; | ||
2067 | struct i2c_adapter *i2c_adap; | 2050 | struct i2c_adapter *i2c_adap; |
2068 | struct channel_obj *ch; | 2051 | struct channel_obj *ch; |
2069 | struct common_obj *common; | 2052 | struct common_obj *common; |
@@ -2086,18 +2069,19 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2086 | return err; | 2069 | return err; |
2087 | } | 2070 | } |
2088 | 2071 | ||
2089 | k = 0; | 2072 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { |
2090 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { | ||
2091 | for (i = res->start; i <= res->end; i++) { | 2073 | for (i = res->start; i <= res->end; i++) { |
2092 | if (request_irq(i, vpif_channel_isr, IRQF_SHARED, | 2074 | if (request_irq(i, vpif_channel_isr, IRQF_SHARED, |
2093 | "VPIF_Capture", | 2075 | "VPIF_Capture", (void *) |
2094 | (void *)(&vpif_obj.dev[k]->channel_id))) { | 2076 | (&vpif_obj.dev[res_idx]->channel_id))) { |
2095 | err = -EBUSY; | 2077 | err = -EBUSY; |
2096 | i--; | 2078 | for (j = 0; j < i; j++) |
2079 | free_irq(j, (void *) | ||
2080 | (&vpif_obj.dev[res_idx]->channel_id)); | ||
2097 | goto vpif_int_err; | 2081 | goto vpif_int_err; |
2098 | } | 2082 | } |
2099 | } | 2083 | } |
2100 | k++; | 2084 | res_idx++; |
2101 | } | 2085 | } |
2102 | 2086 | ||
2103 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { | 2087 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { |
@@ -2111,7 +2095,7 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2111 | video_device_release(ch->video_dev); | 2095 | video_device_release(ch->video_dev); |
2112 | } | 2096 | } |
2113 | err = -ENOMEM; | 2097 | err = -ENOMEM; |
2114 | goto vpif_dev_alloc_err; | 2098 | goto vpif_int_err; |
2115 | } | 2099 | } |
2116 | 2100 | ||
2117 | /* Initialize field of video device */ | 2101 | /* Initialize field of video device */ |
@@ -2142,24 +2126,6 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2142 | } | 2126 | } |
2143 | } | 2127 | } |
2144 | 2128 | ||
2145 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | ||
2146 | ch = vpif_obj.dev[j]; | ||
2147 | ch->channel_id = j; | ||
2148 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
2149 | spin_lock_init(&common->irqlock); | ||
2150 | mutex_init(&common->lock); | ||
2151 | ch->video_dev->lock = &common->lock; | ||
2152 | /* Initialize prio member of channel object */ | ||
2153 | v4l2_prio_init(&ch->prio); | ||
2154 | err = video_register_device(ch->video_dev, | ||
2155 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | ||
2156 | if (err) | ||
2157 | goto probe_out; | ||
2158 | |||
2159 | video_set_drvdata(ch->video_dev, ch); | ||
2160 | |||
2161 | } | ||
2162 | |||
2163 | i2c_adap = i2c_get_adapter(1); | 2129 | i2c_adap = i2c_get_adapter(1); |
2164 | config = pdev->dev.platform_data; | 2130 | config = pdev->dev.platform_data; |
2165 | 2131 | ||
@@ -2169,7 +2135,7 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2169 | if (vpif_obj.sd == NULL) { | 2135 | if (vpif_obj.sd == NULL) { |
2170 | vpif_err("unable to allocate memory for subdevice pointers\n"); | 2136 | vpif_err("unable to allocate memory for subdevice pointers\n"); |
2171 | err = -ENOMEM; | 2137 | err = -ENOMEM; |
2172 | goto probe_out; | 2138 | goto vpif_sd_error; |
2173 | } | 2139 | } |
2174 | 2140 | ||
2175 | for (i = 0; i < subdev_count; i++) { | 2141 | for (i = 0; i < subdev_count; i++) { |
@@ -2186,19 +2152,32 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2186 | } | 2152 | } |
2187 | v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", | 2153 | v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", |
2188 | subdevdata->name); | 2154 | subdevdata->name); |
2189 | |||
2190 | if (vpif_obj.sd[i]) | ||
2191 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
2192 | } | 2155 | } |
2193 | 2156 | ||
2157 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | ||
2158 | ch = vpif_obj.dev[j]; | ||
2159 | ch->channel_id = j; | ||
2160 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
2161 | spin_lock_init(&common->irqlock); | ||
2162 | mutex_init(&common->lock); | ||
2163 | ch->video_dev->lock = &common->lock; | ||
2164 | /* Initialize prio member of channel object */ | ||
2165 | v4l2_prio_init(&ch->prio); | ||
2166 | video_set_drvdata(ch->video_dev, ch); | ||
2167 | |||
2168 | /* select input 0 */ | ||
2169 | err = vpif_set_input(config, ch, 0); | ||
2170 | if (err) | ||
2171 | goto probe_out; | ||
2172 | |||
2173 | err = video_register_device(ch->video_dev, | ||
2174 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | ||
2175 | if (err) | ||
2176 | goto probe_out; | ||
2177 | } | ||
2194 | v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); | 2178 | v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); |
2195 | return 0; | 2179 | return 0; |
2196 | 2180 | ||
2197 | probe_subdev_out: | ||
2198 | /* free sub devices memory */ | ||
2199 | kfree(vpif_obj.sd); | ||
2200 | |||
2201 | j = VPIF_CAPTURE_MAX_DEVICES; | ||
2202 | probe_out: | 2181 | probe_out: |
2203 | for (k = 0; k < j; k++) { | 2182 | for (k = 0; k < j; k++) { |
2204 | /* Get the pointer to the channel object */ | 2183 | /* Get the pointer to the channel object */ |
@@ -2206,22 +2185,23 @@ probe_out: | |||
2206 | /* Unregister video device */ | 2185 | /* Unregister video device */ |
2207 | video_unregister_device(ch->video_dev); | 2186 | video_unregister_device(ch->video_dev); |
2208 | } | 2187 | } |
2188 | probe_subdev_out: | ||
2189 | /* free sub devices memory */ | ||
2190 | kfree(vpif_obj.sd); | ||
2209 | 2191 | ||
2210 | vpif_dev_alloc_err: | 2192 | vpif_sd_error: |
2211 | k = VPIF_CAPTURE_MAX_DEVICES-1; | 2193 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { |
2212 | res = platform_get_resource(pdev, IORESOURCE_IRQ, k); | 2194 | ch = vpif_obj.dev[i]; |
2213 | i = res->end; | 2195 | /* Note: does nothing if ch->video_dev == NULL */ |
2214 | 2196 | video_device_release(ch->video_dev); | |
2215 | vpif_int_err: | ||
2216 | for (q = k; q >= 0; q--) { | ||
2217 | for (m = i; m >= (int)res->start; m--) | ||
2218 | free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id)); | ||
2219 | |||
2220 | res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1); | ||
2221 | if (res) | ||
2222 | i = res->end; | ||
2223 | } | 2197 | } |
2198 | vpif_int_err: | ||
2224 | v4l2_device_unregister(&vpif_obj.v4l2_dev); | 2199 | v4l2_device_unregister(&vpif_obj.v4l2_dev); |
2200 | for (i = 0; i < res_idx; i++) { | ||
2201 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
2202 | for (j = res->start; j <= res->end; j++) | ||
2203 | free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); | ||
2204 | } | ||
2225 | return err; | 2205 | return err; |
2226 | } | 2206 | } |
2227 | 2207 | ||
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index d24efc17e4c8..3d3c1e5cd5d4 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h | |||
@@ -54,8 +54,6 @@ struct video_obj { | |||
54 | /* Currently selected or default standard */ | 54 | /* Currently selected or default standard */ |
55 | v4l2_std_id stdid; | 55 | v4l2_std_id stdid; |
56 | struct v4l2_dv_timings dv_timings; | 56 | struct v4l2_dv_timings dv_timings; |
57 | /* This is to track the last input that is passed to application */ | ||
58 | u32 input_idx; | ||
59 | }; | 57 | }; |
60 | 58 | ||
61 | struct vpif_cap_buffer { | 59 | struct vpif_cap_buffer { |
@@ -119,10 +117,10 @@ struct channel_obj { | |||
119 | u8 initialized; | 117 | u8 initialized; |
120 | /* Identifies channel */ | 118 | /* Identifies channel */ |
121 | enum vpif_channel_id channel_id; | 119 | enum vpif_channel_id channel_id; |
122 | /* index into sd table */ | 120 | /* Current input */ |
123 | int curr_sd_index; | 121 | u32 input_idx; |
124 | /* ptr to current sub device information */ | 122 | /* subdev corresponding to the current input, may be NULL */ |
125 | struct vpif_subdev_info *curr_subdev_info; | 123 | struct v4l2_subdev *sd; |
126 | /* vpif configuration params */ | 124 | /* vpif configuration params */ |
127 | struct vpif_params vpifparams; | 125 | struct vpif_params vpifparams; |
128 | /* common object array */ | 126 | /* common object array */ |
@@ -159,10 +157,6 @@ struct vpif_config_params { | |||
159 | u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS]; | 157 | u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS]; |
160 | u8 max_device_type; | 158 | u8 max_device_type; |
161 | }; | 159 | }; |
162 | /* Struct which keeps track of the line numbers for the sliced vbi service */ | 160 | |
163 | struct vpif_service_line { | ||
164 | u16 service_id; | ||
165 | u16 service_line[2]; | ||
166 | }; | ||
167 | #endif /* End of __KERNEL__ */ | 161 | #endif /* End of __KERNEL__ */ |
168 | #endif /* VPIF_CAPTURE_H */ | 162 | #endif /* VPIF_CAPTURE_H */ |
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index a5b88689abad..b716fbd4241f 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c | |||
@@ -280,12 +280,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
280 | } | 280 | } |
281 | 281 | ||
282 | /* clock settings */ | 282 | /* clock settings */ |
283 | ret = | 283 | if (vpif_config_data->set_clock) { |
284 | vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, | 284 | ret = vpif_config_data->set_clock(ch->vpifparams.std_info. |
285 | ch->vpifparams.std_info.hd_sd); | 285 | ycmux_mode, ch->vpifparams.std_info.hd_sd); |
286 | if (ret < 0) { | 286 | if (ret < 0) { |
287 | vpif_err("can't set clock\n"); | 287 | vpif_err("can't set clock\n"); |
288 | return ret; | 288 | return ret; |
289 | } | ||
289 | } | 290 | } |
290 | 291 | ||
291 | /* set the parameters and addresses */ | 292 | /* set the parameters and addresses */ |
@@ -307,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
307 | channel2_intr_assert(); | 308 | channel2_intr_assert(); |
308 | channel2_intr_enable(1); | 309 | channel2_intr_enable(1); |
309 | enable_channel2(1); | 310 | enable_channel2(1); |
310 | if (vpif_config_data->ch2_clip_en) | 311 | if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en) |
311 | channel2_clipping_enable(1); | 312 | channel2_clipping_enable(1); |
312 | } | 313 | } |
313 | 314 | ||
@@ -316,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
316 | channel3_intr_assert(); | 317 | channel3_intr_assert(); |
317 | channel3_intr_enable(1); | 318 | channel3_intr_enable(1); |
318 | enable_channel3(1); | 319 | enable_channel3(1); |
319 | if (vpif_config_data->ch3_clip_en) | 320 | if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en) |
320 | channel3_clipping_enable(1); | 321 | channel3_clipping_enable(1); |
321 | } | 322 | } |
322 | 323 | ||
@@ -826,9 +827,11 @@ static int vpif_querycap(struct file *file, void *priv, | |||
826 | { | 827 | { |
827 | struct vpif_display_config *config = vpif_dev->platform_data; | 828 | struct vpif_display_config *config = vpif_dev->platform_data; |
828 | 829 | ||
829 | cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; | 830 | cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; |
830 | strlcpy(cap->driver, "vpif display", sizeof(cap->driver)); | 831 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
831 | strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info)); | 832 | snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); |
833 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", | ||
834 | dev_name(vpif_dev)); | ||
832 | strlcpy(cap->card, config->card_name, sizeof(cap->card)); | 835 | strlcpy(cap->card, config->card_name, sizeof(cap->card)); |
833 | 836 | ||
834 | return 0; | 837 | return 0; |
@@ -935,6 +938,7 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
935 | enum v4l2_field field; | 938 | enum v4l2_field field; |
936 | struct vb2_queue *q; | 939 | struct vb2_queue *q; |
937 | u8 index = 0; | 940 | u8 index = 0; |
941 | int ret; | ||
938 | 942 | ||
939 | /* This file handle has not initialized the channel, | 943 | /* This file handle has not initialized the channel, |
940 | It is not allowed to do settings */ | 944 | It is not allowed to do settings */ |
@@ -980,8 +984,12 @@ static int vpif_reqbufs(struct file *file, void *priv, | |||
980 | q->mem_ops = &vb2_dma_contig_memops; | 984 | q->mem_ops = &vb2_dma_contig_memops; |
981 | q->buf_struct_size = sizeof(struct vpif_disp_buffer); | 985 | q->buf_struct_size = sizeof(struct vpif_disp_buffer); |
982 | 986 | ||
983 | vb2_queue_init(q); | 987 | ret = vb2_queue_init(q); |
984 | 988 | if (ret) { | |
989 | vpif_err("vpif_display: vb2_queue_init() failed\n"); | ||
990 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | ||
991 | return ret; | ||
992 | } | ||
985 | /* Set io allowed member of file handle to TRUE */ | 993 | /* Set io allowed member of file handle to TRUE */ |
986 | fh->io_allowed[index] = 1; | 994 | fh->io_allowed[index] = 1; |
987 | /* Increment io usrs member of channel object to 1 */ | 995 | /* Increment io usrs member of channel object to 1 */ |
@@ -1173,14 +1181,16 @@ static int vpif_streamoff(struct file *file, void *priv, | |||
1173 | if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | 1181 | if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
1174 | /* disable channel */ | 1182 | /* disable channel */ |
1175 | if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { | 1183 | if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { |
1176 | if (vpif_config_data->ch2_clip_en) | 1184 | if (vpif_config_data-> |
1185 | chan_config[VPIF_CHANNEL2_VIDEO].clip_en) | ||
1177 | channel2_clipping_enable(0); | 1186 | channel2_clipping_enable(0); |
1178 | enable_channel2(0); | 1187 | enable_channel2(0); |
1179 | channel2_intr_enable(0); | 1188 | channel2_intr_enable(0); |
1180 | } | 1189 | } |
1181 | if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || | 1190 | if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || |
1182 | (2 == common->started)) { | 1191 | (2 == common->started)) { |
1183 | if (vpif_config_data->ch3_clip_en) | 1192 | if (vpif_config_data-> |
1193 | chan_config[VPIF_CHANNEL3_VIDEO].clip_en) | ||
1184 | channel3_clipping_enable(0); | 1194 | channel3_clipping_enable(0); |
1185 | enable_channel3(0); | 1195 | enable_channel3(0); |
1186 | channel3_intr_enable(0); | 1196 | channel3_intr_enable(0); |
@@ -1213,49 +1223,126 @@ static int vpif_enum_output(struct file *file, void *fh, | |||
1213 | { | 1223 | { |
1214 | 1224 | ||
1215 | struct vpif_display_config *config = vpif_dev->platform_data; | 1225 | struct vpif_display_config *config = vpif_dev->platform_data; |
1226 | struct vpif_display_chan_config *chan_cfg; | ||
1227 | struct vpif_fh *vpif_handler = fh; | ||
1228 | struct channel_obj *ch = vpif_handler->channel; | ||
1216 | 1229 | ||
1217 | if (output->index >= config->output_count) { | 1230 | chan_cfg = &config->chan_config[ch->channel_id]; |
1231 | if (output->index >= chan_cfg->output_count) { | ||
1218 | vpif_dbg(1, debug, "Invalid output index\n"); | 1232 | vpif_dbg(1, debug, "Invalid output index\n"); |
1219 | return -EINVAL; | 1233 | return -EINVAL; |
1220 | } | 1234 | } |
1221 | 1235 | ||
1222 | strcpy(output->name, config->output[output->index]); | 1236 | *output = chan_cfg->outputs[output->index].output; |
1223 | output->type = V4L2_OUTPUT_TYPE_ANALOG; | 1237 | return 0; |
1224 | output->std = VPIF_V4L2_STD; | 1238 | } |
1239 | |||
1240 | /** | ||
1241 | * vpif_output_to_subdev() - Maps output to sub device | ||
1242 | * @vpif_cfg - global config ptr | ||
1243 | * @chan_cfg - channel config ptr | ||
1244 | * @index - Given output index from application | ||
1245 | * | ||
1246 | * lookup the sub device information for a given output index. | ||
1247 | * we report all the output to application. output table also | ||
1248 | * has sub device name for the each output | ||
1249 | */ | ||
1250 | static int | ||
1251 | vpif_output_to_subdev(struct vpif_display_config *vpif_cfg, | ||
1252 | struct vpif_display_chan_config *chan_cfg, int index) | ||
1253 | { | ||
1254 | struct vpif_subdev_info *subdev_info; | ||
1255 | const char *subdev_name; | ||
1256 | int i; | ||
1257 | |||
1258 | vpif_dbg(2, debug, "vpif_output_to_subdev\n"); | ||
1259 | |||
1260 | if (chan_cfg->outputs == NULL) | ||
1261 | return -1; | ||
1262 | |||
1263 | subdev_name = chan_cfg->outputs[index].subdev_name; | ||
1264 | if (subdev_name == NULL) | ||
1265 | return -1; | ||
1266 | |||
1267 | /* loop through the sub device list to get the sub device info */ | ||
1268 | for (i = 0; i < vpif_cfg->subdev_count; i++) { | ||
1269 | subdev_info = &vpif_cfg->subdevinfo[i]; | ||
1270 | if (!strcmp(subdev_info->name, subdev_name)) | ||
1271 | return i; | ||
1272 | } | ||
1273 | return -1; | ||
1274 | } | ||
1275 | |||
1276 | /** | ||
1277 | * vpif_set_output() - Select an output | ||
1278 | * @vpif_cfg - global config ptr | ||
1279 | * @ch - channel | ||
1280 | * @index - Given output index from application | ||
1281 | * | ||
1282 | * Select the given output. | ||
1283 | */ | ||
1284 | static int vpif_set_output(struct vpif_display_config *vpif_cfg, | ||
1285 | struct channel_obj *ch, int index) | ||
1286 | { | ||
1287 | struct vpif_display_chan_config *chan_cfg = | ||
1288 | &vpif_cfg->chan_config[ch->channel_id]; | ||
1289 | struct vpif_subdev_info *subdev_info = NULL; | ||
1290 | struct v4l2_subdev *sd = NULL; | ||
1291 | u32 input = 0, output = 0; | ||
1292 | int sd_index; | ||
1293 | int ret; | ||
1294 | |||
1295 | sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index); | ||
1296 | if (sd_index >= 0) { | ||
1297 | sd = vpif_obj.sd[sd_index]; | ||
1298 | subdev_info = &vpif_cfg->subdevinfo[sd_index]; | ||
1299 | } | ||
1300 | |||
1301 | if (sd) { | ||
1302 | input = chan_cfg->outputs[index].input_route; | ||
1303 | output = chan_cfg->outputs[index].output_route; | ||
1304 | ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0); | ||
1305 | if (ret < 0 && ret != -ENOIOCTLCMD) { | ||
1306 | vpif_err("Failed to set output\n"); | ||
1307 | return ret; | ||
1308 | } | ||
1225 | 1309 | ||
1310 | } | ||
1311 | ch->output_idx = index; | ||
1312 | ch->sd = sd; | ||
1313 | if (chan_cfg->outputs != NULL) | ||
1314 | /* update tvnorms from the sub device output info */ | ||
1315 | ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std; | ||
1226 | return 0; | 1316 | return 0; |
1227 | } | 1317 | } |
1228 | 1318 | ||
1229 | static int vpif_s_output(struct file *file, void *priv, unsigned int i) | 1319 | static int vpif_s_output(struct file *file, void *priv, unsigned int i) |
1230 | { | 1320 | { |
1321 | struct vpif_display_config *config = vpif_dev->platform_data; | ||
1322 | struct vpif_display_chan_config *chan_cfg; | ||
1231 | struct vpif_fh *fh = priv; | 1323 | struct vpif_fh *fh = priv; |
1232 | struct channel_obj *ch = fh->channel; | 1324 | struct channel_obj *ch = fh->channel; |
1233 | struct video_obj *vid_ch = &ch->video; | ||
1234 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 1325 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
1235 | int ret = 0; | 1326 | |
1327 | chan_cfg = &config->chan_config[ch->channel_id]; | ||
1328 | |||
1329 | if (i >= chan_cfg->output_count) | ||
1330 | return -EINVAL; | ||
1236 | 1331 | ||
1237 | if (common->started) { | 1332 | if (common->started) { |
1238 | vpif_err("Streaming in progress\n"); | 1333 | vpif_err("Streaming in progress\n"); |
1239 | return -EBUSY; | 1334 | return -EBUSY; |
1240 | } | 1335 | } |
1241 | 1336 | ||
1242 | ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, | 1337 | return vpif_set_output(config, ch, i); |
1243 | s_routing, 0, i, 0); | ||
1244 | |||
1245 | if (ret < 0) | ||
1246 | vpif_err("Failed to set output standard\n"); | ||
1247 | |||
1248 | vid_ch->output_id = i; | ||
1249 | return ret; | ||
1250 | } | 1338 | } |
1251 | 1339 | ||
1252 | static int vpif_g_output(struct file *file, void *priv, unsigned int *i) | 1340 | static int vpif_g_output(struct file *file, void *priv, unsigned int *i) |
1253 | { | 1341 | { |
1254 | struct vpif_fh *fh = priv; | 1342 | struct vpif_fh *fh = priv; |
1255 | struct channel_obj *ch = fh->channel; | 1343 | struct channel_obj *ch = fh->channel; |
1256 | struct video_obj *vid_ch = &ch->video; | ||
1257 | 1344 | ||
1258 | *i = vid_ch->output_id; | 1345 | *i = ch->output_idx; |
1259 | 1346 | ||
1260 | return 0; | 1347 | return 0; |
1261 | } | 1348 | } |
@@ -1290,10 +1377,12 @@ vpif_enum_dv_timings(struct file *file, void *priv, | |||
1290 | { | 1377 | { |
1291 | struct vpif_fh *fh = priv; | 1378 | struct vpif_fh *fh = priv; |
1292 | struct channel_obj *ch = fh->channel; | 1379 | struct channel_obj *ch = fh->channel; |
1293 | struct video_obj *vid_ch = &ch->video; | 1380 | int ret; |
1294 | 1381 | ||
1295 | return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], | 1382 | ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); |
1296 | video, enum_dv_timings, timings); | 1383 | if (ret == -ENOIOCTLCMD && ret == -ENODEV) |
1384 | return -EINVAL; | ||
1385 | return ret; | ||
1297 | } | 1386 | } |
1298 | 1387 | ||
1299 | /** | 1388 | /** |
@@ -1319,13 +1408,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
1319 | } | 1408 | } |
1320 | 1409 | ||
1321 | /* Configure subdevice timings, if any */ | 1410 | /* Configure subdevice timings, if any */ |
1322 | ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], | 1411 | ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); |
1323 | video, s_dv_timings, timings); | 1412 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
1324 | if (ret == -ENOIOCTLCMD) { | 1413 | ret = 0; |
1325 | vpif_dbg(2, debug, "Custom DV timings not supported by " | ||
1326 | "subdevice\n"); | ||
1327 | return -EINVAL; | ||
1328 | } | ||
1329 | if (ret < 0) { | 1414 | if (ret < 0) { |
1330 | vpif_dbg(2, debug, "Error setting custom DV timings\n"); | 1415 | vpif_dbg(2, debug, "Error setting custom DV timings\n"); |
1331 | return ret; | 1416 | return ret; |
@@ -1450,10 +1535,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv, | |||
1450 | struct v4l2_dbg_register *reg){ | 1535 | struct v4l2_dbg_register *reg){ |
1451 | struct vpif_fh *fh = priv; | 1536 | struct vpif_fh *fh = priv; |
1452 | struct channel_obj *ch = fh->channel; | 1537 | struct channel_obj *ch = fh->channel; |
1453 | struct video_obj *vid_ch = &ch->video; | ||
1454 | 1538 | ||
1455 | return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core, | 1539 | return v4l2_subdev_call(ch->sd, core, g_register, reg); |
1456 | g_register, reg); | ||
1457 | } | 1540 | } |
1458 | 1541 | ||
1459 | /* | 1542 | /* |
@@ -1469,10 +1552,8 @@ static int vpif_dbg_s_register(struct file *file, void *priv, | |||
1469 | struct v4l2_dbg_register *reg){ | 1552 | struct v4l2_dbg_register *reg){ |
1470 | struct vpif_fh *fh = priv; | 1553 | struct vpif_fh *fh = priv; |
1471 | struct channel_obj *ch = fh->channel; | 1554 | struct channel_obj *ch = fh->channel; |
1472 | struct video_obj *vid_ch = &ch->video; | ||
1473 | 1555 | ||
1474 | return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core, | 1556 | return v4l2_subdev_call(ch->sd, core, s_register, reg); |
1475 | s_register, reg); | ||
1476 | } | 1557 | } |
1477 | #endif | 1558 | #endif |
1478 | 1559 | ||
@@ -1536,9 +1617,6 @@ static struct video_device vpif_video_template = { | |||
1536 | .name = "vpif", | 1617 | .name = "vpif", |
1537 | .fops = &vpif_fops, | 1618 | .fops = &vpif_fops, |
1538 | .ioctl_ops = &vpif_ioctl_ops, | 1619 | .ioctl_ops = &vpif_ioctl_ops, |
1539 | .tvnorms = VPIF_V4L2_STD, | ||
1540 | .current_norm = V4L2_STD_625_50, | ||
1541 | |||
1542 | }; | 1620 | }; |
1543 | 1621 | ||
1544 | /*Configure the channels, buffer sizei, request irq */ | 1622 | /*Configure the channels, buffer sizei, request irq */ |
@@ -1611,7 +1689,8 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1611 | { | 1689 | { |
1612 | struct vpif_subdev_info *subdevdata; | 1690 | struct vpif_subdev_info *subdevdata; |
1613 | struct vpif_display_config *config; | 1691 | struct vpif_display_config *config; |
1614 | int i, j = 0, k, q, m, err = 0; | 1692 | int i, j = 0, k, err = 0; |
1693 | int res_idx = 0; | ||
1615 | struct i2c_adapter *i2c_adap; | 1694 | struct i2c_adapter *i2c_adap; |
1616 | struct common_obj *common; | 1695 | struct common_obj *common; |
1617 | struct channel_obj *ch; | 1696 | struct channel_obj *ch; |
@@ -1634,21 +1713,22 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1634 | return err; | 1713 | return err; |
1635 | } | 1714 | } |
1636 | 1715 | ||
1637 | k = 0; | 1716 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { |
1638 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { | ||
1639 | for (i = res->start; i <= res->end; i++) { | 1717 | for (i = res->start; i <= res->end; i++) { |
1640 | if (request_irq(i, vpif_channel_isr, IRQF_SHARED, | 1718 | if (request_irq(i, vpif_channel_isr, IRQF_SHARED, |
1641 | "VPIF_Display", | 1719 | "VPIF_Display", (void *) |
1642 | (void *)(&vpif_obj.dev[k]->channel_id))) { | 1720 | (&vpif_obj.dev[res_idx]->channel_id))) { |
1643 | err = -EBUSY; | 1721 | err = -EBUSY; |
1722 | for (j = 0; j < i; j++) | ||
1723 | free_irq(j, (void *) | ||
1724 | (&vpif_obj.dev[res_idx]->channel_id)); | ||
1644 | goto vpif_int_err; | 1725 | goto vpif_int_err; |
1645 | } | 1726 | } |
1646 | } | 1727 | } |
1647 | k++; | 1728 | res_idx++; |
1648 | } | 1729 | } |
1649 | 1730 | ||
1650 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { | 1731 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { |
1651 | |||
1652 | /* Get the pointer to the channel object */ | 1732 | /* Get the pointer to the channel object */ |
1653 | ch = vpif_obj.dev[i]; | 1733 | ch = vpif_obj.dev[i]; |
1654 | 1734 | ||
@@ -1694,6 +1774,32 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1694 | } | 1774 | } |
1695 | } | 1775 | } |
1696 | 1776 | ||
1777 | i2c_adap = i2c_get_adapter(1); | ||
1778 | config = pdev->dev.platform_data; | ||
1779 | subdev_count = config->subdev_count; | ||
1780 | subdevdata = config->subdevinfo; | ||
1781 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, | ||
1782 | GFP_KERNEL); | ||
1783 | if (vpif_obj.sd == NULL) { | ||
1784 | vpif_err("unable to allocate memory for subdevice pointers\n"); | ||
1785 | err = -ENOMEM; | ||
1786 | goto vpif_sd_error; | ||
1787 | } | ||
1788 | |||
1789 | for (i = 0; i < subdev_count; i++) { | ||
1790 | vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, | ||
1791 | i2c_adap, | ||
1792 | &subdevdata[i].board_info, | ||
1793 | NULL); | ||
1794 | if (!vpif_obj.sd[i]) { | ||
1795 | vpif_err("Error registering v4l2 subdevice\n"); | ||
1796 | goto probe_subdev_out; | ||
1797 | } | ||
1798 | |||
1799 | if (vpif_obj.sd[i]) | ||
1800 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
1801 | } | ||
1802 | |||
1697 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { | 1803 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { |
1698 | ch = vpif_obj.dev[j]; | 1804 | ch = vpif_obj.dev[j]; |
1699 | /* Initialize field of the channel objects */ | 1805 | /* Initialize field of the channel objects */ |
@@ -1715,6 +1821,8 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1715 | 1821 | ||
1716 | } | 1822 | } |
1717 | ch->initialized = 0; | 1823 | ch->initialized = 0; |
1824 | if (subdev_count) | ||
1825 | ch->sd = vpif_obj.sd[0]; | ||
1718 | ch->channel_id = j; | 1826 | ch->channel_id = j; |
1719 | if (j < 2) | 1827 | if (j < 2) |
1720 | ch->common[VPIF_VIDEO_INDEX].numbuffers = | 1828 | ch->common[VPIF_VIDEO_INDEX].numbuffers = |
@@ -1729,6 +1837,12 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1729 | ch->common[VPIF_VIDEO_INDEX].fmt.type = | 1837 | ch->common[VPIF_VIDEO_INDEX].fmt.type = |
1730 | V4L2_BUF_TYPE_VIDEO_OUTPUT; | 1838 | V4L2_BUF_TYPE_VIDEO_OUTPUT; |
1731 | ch->video_dev->lock = &common->lock; | 1839 | ch->video_dev->lock = &common->lock; |
1840 | video_set_drvdata(ch->video_dev, ch); | ||
1841 | |||
1842 | /* select output 0 */ | ||
1843 | err = vpif_set_output(config, ch, 0); | ||
1844 | if (err) | ||
1845 | goto probe_out; | ||
1732 | 1846 | ||
1733 | /* register video device */ | 1847 | /* register video device */ |
1734 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", | 1848 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", |
@@ -1738,42 +1852,12 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
1738 | VFL_TYPE_GRABBER, (j ? 3 : 2)); | 1852 | VFL_TYPE_GRABBER, (j ? 3 : 2)); |
1739 | if (err < 0) | 1853 | if (err < 0) |
1740 | goto probe_out; | 1854 | goto probe_out; |
1741 | |||
1742 | video_set_drvdata(ch->video_dev, ch); | ||
1743 | } | ||
1744 | |||
1745 | i2c_adap = i2c_get_adapter(1); | ||
1746 | config = pdev->dev.platform_data; | ||
1747 | subdev_count = config->subdev_count; | ||
1748 | subdevdata = config->subdevinfo; | ||
1749 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, | ||
1750 | GFP_KERNEL); | ||
1751 | if (vpif_obj.sd == NULL) { | ||
1752 | vpif_err("unable to allocate memory for subdevice pointers\n"); | ||
1753 | err = -ENOMEM; | ||
1754 | goto probe_out; | ||
1755 | } | ||
1756 | |||
1757 | for (i = 0; i < subdev_count; i++) { | ||
1758 | vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, | ||
1759 | i2c_adap, | ||
1760 | &subdevdata[i].board_info, | ||
1761 | NULL); | ||
1762 | if (!vpif_obj.sd[i]) { | ||
1763 | vpif_err("Error registering v4l2 subdevice\n"); | ||
1764 | goto probe_subdev_out; | ||
1765 | } | ||
1766 | |||
1767 | if (vpif_obj.sd[i]) | ||
1768 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
1769 | } | 1855 | } |
1770 | 1856 | ||
1771 | v4l2_info(&vpif_obj.v4l2_dev, | 1857 | v4l2_info(&vpif_obj.v4l2_dev, |
1772 | " VPIF display driver initialized\n"); | 1858 | " VPIF display driver initialized\n"); |
1773 | return 0; | 1859 | return 0; |
1774 | 1860 | ||
1775 | probe_subdev_out: | ||
1776 | kfree(vpif_obj.sd); | ||
1777 | probe_out: | 1861 | probe_out: |
1778 | for (k = 0; k < j; k++) { | 1862 | for (k = 0; k < j; k++) { |
1779 | ch = vpif_obj.dev[k]; | 1863 | ch = vpif_obj.dev[k]; |
@@ -1781,14 +1865,21 @@ probe_out: | |||
1781 | video_device_release(ch->video_dev); | 1865 | video_device_release(ch->video_dev); |
1782 | ch->video_dev = NULL; | 1866 | ch->video_dev = NULL; |
1783 | } | 1867 | } |
1868 | probe_subdev_out: | ||
1869 | kfree(vpif_obj.sd); | ||
1870 | vpif_sd_error: | ||
1871 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { | ||
1872 | ch = vpif_obj.dev[i]; | ||
1873 | /* Note: does nothing if ch->video_dev == NULL */ | ||
1874 | video_device_release(ch->video_dev); | ||
1875 | } | ||
1784 | vpif_int_err: | 1876 | vpif_int_err: |
1785 | v4l2_device_unregister(&vpif_obj.v4l2_dev); | 1877 | v4l2_device_unregister(&vpif_obj.v4l2_dev); |
1786 | vpif_err("VPIF IRQ request failed\n"); | 1878 | vpif_err("VPIF IRQ request failed\n"); |
1787 | for (q = k; k >= 0; k--) { | 1879 | for (i = 0; i < res_idx; i++) { |
1788 | for (m = i; m >= res->start; m--) | 1880 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); |
1789 | free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id)); | 1881 | for (j = res->start; j <= res->end; j++) |
1790 | res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1); | 1882 | free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); |
1791 | m = res->end; | ||
1792 | } | 1883 | } |
1793 | 1884 | ||
1794 | return err; | 1885 | return err; |
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index f628ebcf3674..a5a18f74395c 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h | |||
@@ -62,13 +62,6 @@ struct video_obj { | |||
62 | v4l2_std_id stdid; /* Currently selected or default | 62 | v4l2_std_id stdid; /* Currently selected or default |
63 | * standard */ | 63 | * standard */ |
64 | struct v4l2_dv_timings dv_timings; | 64 | struct v4l2_dv_timings dv_timings; |
65 | u32 output_id; /* Current output id */ | ||
66 | }; | ||
67 | |||
68 | struct vbi_obj { | ||
69 | int num_services; | ||
70 | struct vpif_vbi_params vbiparams; /* vpif parameters for the raw | ||
71 | * vbi data */ | ||
72 | }; | 65 | }; |
73 | 66 | ||
74 | struct vpif_disp_buffer { | 67 | struct vpif_disp_buffer { |
@@ -131,12 +124,13 @@ struct channel_obj { | |||
131 | * which is being displayed */ | 124 | * which is being displayed */ |
132 | u8 initialized; /* flag to indicate whether | 125 | u8 initialized; /* flag to indicate whether |
133 | * encoder is initialized */ | 126 | * encoder is initialized */ |
127 | u32 output_idx; /* Current output index */ | ||
128 | struct v4l2_subdev *sd; /* Current output subdev(may be NULL) */ | ||
134 | 129 | ||
135 | enum vpif_channel_id channel_id;/* Identifies channel */ | 130 | enum vpif_channel_id channel_id;/* Identifies channel */ |
136 | struct vpif_params vpifparams; | 131 | struct vpif_params vpifparams; |
137 | struct common_obj common[VPIF_NUMOBJECTS]; | 132 | struct common_obj common[VPIF_NUMOBJECTS]; |
138 | struct video_obj video; | 133 | struct video_obj video; |
139 | struct vbi_obj vbi; | ||
140 | }; | 134 | }; |
141 | 135 | ||
142 | /* File handle structure */ | 136 | /* File handle structure */ |
@@ -168,12 +162,4 @@ struct vpif_config_params { | |||
168 | u8 min_numbuffers; | 162 | u8 min_numbuffers; |
169 | }; | 163 | }; |
170 | 164 | ||
171 | /* Struct which keeps track of the line numbers for the sliced vbi service */ | ||
172 | struct vpif_service_line { | ||
173 | u16 service_id; | ||
174 | u16 service_line[2]; | ||
175 | u16 enc_service_id; | ||
176 | u8 bytestowrite; | ||
177 | }; | ||
178 | |||
179 | #endif /* DAVINCIHD_DISPLAY_H */ | 165 | #endif /* DAVINCIHD_DISPLAY_H */ |
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c index 0d8625f03a32..0146b354dc22 100644 --- a/drivers/media/platform/exynos-gsc/gsc-regs.c +++ b/drivers/media/platform/exynos-gsc/gsc-regs.c | |||
@@ -212,7 +212,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) | |||
212 | else | 212 | else |
213 | cfg |= GSC_IN_YUV422_3P; | 213 | cfg |= GSC_IN_YUV422_3P; |
214 | break; | 214 | break; |
215 | }; | 215 | } |
216 | 216 | ||
217 | writel(cfg, dev->regs + GSC_IN_CON); | 217 | writel(cfg, dev->regs + GSC_IN_CON); |
218 | } | 218 | } |
@@ -332,7 +332,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) | |||
332 | case 3: | 332 | case 3: |
333 | cfg |= GSC_OUT_YUV420_3P; | 333 | cfg |= GSC_OUT_YUV420_3P; |
334 | break; | 334 | break; |
335 | }; | 335 | } |
336 | 336 | ||
337 | end_set: | 337 | end_set: |
338 | writel(cfg, dev->regs + GSC_OUT_CON); | 338 | writel(cfg, dev->regs + GSC_OUT_CON); |
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 897250b88647..31ac4dc69247 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c | |||
@@ -864,7 +864,7 @@ int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer * | |||
864 | { | 864 | { |
865 | struct viu_fh *fh = priv; | 865 | struct viu_fh *fh = priv; |
866 | struct viu_dev *dev = fh->dev; | 866 | struct viu_dev *dev = fh->dev; |
867 | struct v4l2_framebuffer *fb = arg; | 867 | const struct v4l2_framebuffer *fb = arg; |
868 | struct viu_fmt *fmt; | 868 | struct viu_fmt *fmt; |
869 | 869 | ||
870 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) | 870 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) |
diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index d03637537118..2e2121e98133 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c | |||
@@ -397,8 +397,7 @@ static void device_isr(unsigned long priv) | |||
397 | curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev); | 397 | curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev); |
398 | 398 | ||
399 | if (NULL == curr_ctx) { | 399 | if (NULL == curr_ctx) { |
400 | printk(KERN_ERR | 400 | pr_err("Instance released before the end of transaction\n"); |
401 | "Instance released before the end of transaction\n"); | ||
402 | return; | 401 | return; |
403 | } | 402 | } |
404 | 403 | ||
@@ -894,7 +893,7 @@ static int m2mtest_open(struct file *file) | |||
894 | 893 | ||
895 | if (mutex_lock_interruptible(&dev->dev_mutex)) | 894 | if (mutex_lock_interruptible(&dev->dev_mutex)) |
896 | return -ERESTARTSYS; | 895 | return -ERESTARTSYS; |
897 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 896 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
898 | if (!ctx) { | 897 | if (!ctx) { |
899 | rc = -ENOMEM; | 898 | rc = -ENOMEM; |
900 | goto open_unlock; | 899 | goto open_unlock; |
@@ -1020,7 +1019,7 @@ static int m2mtest_probe(struct platform_device *pdev) | |||
1020 | struct video_device *vfd; | 1019 | struct video_device *vfd; |
1021 | int ret; | 1020 | int ret; |
1022 | 1021 | ||
1023 | dev = kzalloc(sizeof *dev, GFP_KERNEL); | 1022 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); |
1024 | if (!dev) | 1023 | if (!dev) |
1025 | return -ENOMEM; | 1024 | return -ENOMEM; |
1026 | 1025 | ||
@@ -1028,7 +1027,7 @@ static int m2mtest_probe(struct platform_device *pdev) | |||
1028 | 1027 | ||
1029 | ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); | 1028 | ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); |
1030 | if (ret) | 1029 | if (ret) |
1031 | goto free_dev; | 1030 | return ret; |
1032 | 1031 | ||
1033 | atomic_set(&dev->num_inst, 0); | 1032 | atomic_set(&dev->num_inst, 0); |
1034 | mutex_init(&dev->dev_mutex); | 1033 | mutex_init(&dev->dev_mutex); |
@@ -1067,15 +1066,13 @@ static int m2mtest_probe(struct platform_device *pdev) | |||
1067 | 1066 | ||
1068 | return 0; | 1067 | return 0; |
1069 | 1068 | ||
1070 | v4l2_m2m_release(dev->m2m_dev); | ||
1071 | err_m2m: | 1069 | err_m2m: |
1070 | v4l2_m2m_release(dev->m2m_dev); | ||
1072 | video_unregister_device(dev->vfd); | 1071 | video_unregister_device(dev->vfd); |
1073 | rel_vdev: | 1072 | rel_vdev: |
1074 | video_device_release(vfd); | 1073 | video_device_release(vfd); |
1075 | unreg_dev: | 1074 | unreg_dev: |
1076 | v4l2_device_unregister(&dev->v4l2_dev); | 1075 | v4l2_device_unregister(&dev->v4l2_dev); |
1077 | free_dev: | ||
1078 | kfree(dev); | ||
1079 | 1076 | ||
1080 | return ret; | 1077 | return ret; |
1081 | } | 1078 | } |
@@ -1090,7 +1087,6 @@ static int m2mtest_remove(struct platform_device *pdev) | |||
1090 | del_timer_sync(&dev->timer); | 1087 | del_timer_sync(&dev->timer); |
1091 | video_unregister_device(dev->vfd); | 1088 | video_unregister_device(dev->vfd); |
1092 | v4l2_device_unregister(&dev->v4l2_dev); | 1089 | v4l2_device_unregister(&dev->v4l2_dev); |
1093 | kfree(dev); | ||
1094 | 1090 | ||
1095 | return 0; | 1091 | return 0; |
1096 | } | 1092 | } |
diff --git a/drivers/media/platform/omap3isp/ispreg.h b/drivers/media/platform/omap3isp/ispreg.h index 084ea77d65a7..e2c57f334c5d 100644 --- a/drivers/media/platform/omap3isp/ispreg.h +++ b/drivers/media/platform/omap3isp/ispreg.h | |||
@@ -27,13 +27,13 @@ | |||
27 | #ifndef OMAP3_ISP_REG_H | 27 | #ifndef OMAP3_ISP_REG_H |
28 | #define OMAP3_ISP_REG_H | 28 | #define OMAP3_ISP_REG_H |
29 | 29 | ||
30 | #include <plat/omap34xx.h> | ||
31 | |||
32 | |||
33 | #define CM_CAM_MCLK_HZ 172800000 /* Hz */ | 30 | #define CM_CAM_MCLK_HZ 172800000 /* Hz */ |
34 | 31 | ||
35 | /* ISP Submodules offset */ | 32 | /* ISP Submodules offset */ |
36 | 33 | ||
34 | #define L4_34XX_BASE 0x48000000 | ||
35 | #define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000) | ||
36 | |||
37 | #define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE | 37 | #define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE |
38 | #define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset)) | 38 | #define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset)) |
39 | 39 | ||
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c index dded98815220..367efd164d0f 100644 --- a/drivers/media/platform/s5p-fimc/fimc-capture.c +++ b/drivers/media/platform/s5p-fimc/fimc-capture.c | |||
@@ -177,7 +177,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx) | |||
177 | 177 | ||
178 | void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) | 178 | void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) |
179 | { | 179 | { |
180 | struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS]; | ||
180 | struct fimc_vid_cap *cap = &fimc->vid_cap; | 181 | struct fimc_vid_cap *cap = &fimc->vid_cap; |
182 | struct fimc_frame *f = &cap->ctx->d_frame; | ||
181 | struct fimc_vid_buffer *v_buf; | 183 | struct fimc_vid_buffer *v_buf; |
182 | struct timeval *tv; | 184 | struct timeval *tv; |
183 | struct timespec ts; | 185 | struct timespec ts; |
@@ -216,6 +218,25 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) | |||
216 | if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) | 218 | if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) |
217 | cap->buf_index = 0; | 219 | cap->buf_index = 0; |
218 | } | 220 | } |
221 | /* | ||
222 | * Set up a buffer at MIPI-CSIS if current image format | ||
223 | * requires the frame embedded data capture. | ||
224 | */ | ||
225 | if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) { | ||
226 | unsigned int plane = ffs(f->fmt->mdataplanes) - 1; | ||
227 | unsigned int size = f->payload[plane]; | ||
228 | s32 index = fimc_hw_get_frame_index(fimc); | ||
229 | void *vaddr; | ||
230 | |||
231 | list_for_each_entry(v_buf, &cap->active_buf_q, list) { | ||
232 | if (v_buf->index != index) | ||
233 | continue; | ||
234 | vaddr = vb2_plane_vaddr(&v_buf->vb, plane); | ||
235 | v4l2_subdev_call(csis, video, s_rx_buffer, | ||
236 | vaddr, &size); | ||
237 | break; | ||
238 | } | ||
239 | } | ||
219 | 240 | ||
220 | if (cap->active_buf_cnt == 0) { | 241 | if (cap->active_buf_cnt == 0) { |
221 | if (deq_buf) | 242 | if (deq_buf) |
@@ -351,6 +372,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, | |||
351 | unsigned int size = (wh * fmt->depth[i]) / 8; | 372 | unsigned int size = (wh * fmt->depth[i]) / 8; |
352 | if (pixm) | 373 | if (pixm) |
353 | sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); | 374 | sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); |
375 | else if (fimc_fmt_is_user_defined(fmt->color)) | ||
376 | sizes[i] = frame->payload[i]; | ||
354 | else | 377 | else |
355 | sizes[i] = max_t(u32, size, frame->payload[i]); | 378 | sizes[i] = max_t(u32, size, frame->payload[i]); |
356 | 379 | ||
@@ -611,10 +634,10 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx, | |||
611 | u32 mask = FMT_FLAGS_CAM; | 634 | u32 mask = FMT_FLAGS_CAM; |
612 | struct fimc_fmt *ffmt; | 635 | struct fimc_fmt *ffmt; |
613 | 636 | ||
614 | /* Color conversion from/to JPEG is not supported */ | 637 | /* Conversion from/to JPEG or User Defined format is not supported */ |
615 | if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE && | 638 | if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE && |
616 | fimc_fmt_is_jpeg(ctx->s_frame.fmt->color)) | 639 | fimc_fmt_is_user_defined(ctx->s_frame.fmt->color)) |
617 | *code = V4L2_MBUS_FMT_JPEG_1X8; | 640 | *code = ctx->s_frame.fmt->mbus_code; |
618 | 641 | ||
619 | if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK) | 642 | if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK) |
620 | mask |= FMT_FLAGS_M2M; | 643 | mask |= FMT_FLAGS_M2M; |
@@ -628,18 +651,19 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx, | |||
628 | *fourcc = ffmt->fourcc; | 651 | *fourcc = ffmt->fourcc; |
629 | 652 | ||
630 | if (pad == FIMC_SD_PAD_SINK) { | 653 | if (pad == FIMC_SD_PAD_SINK) { |
631 | max_w = fimc_fmt_is_jpeg(ffmt->color) ? | 654 | max_w = fimc_fmt_is_user_defined(ffmt->color) ? |
632 | pl->scaler_dis_w : pl->scaler_en_w; | 655 | pl->scaler_dis_w : pl->scaler_en_w; |
633 | /* Apply the camera input interface pixel constraints */ | 656 | /* Apply the camera input interface pixel constraints */ |
634 | v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4, | 657 | v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4, |
635 | height, max_t(u32, *height, 32), | 658 | height, max_t(u32, *height, 32), |
636 | FIMC_CAMIF_MAX_HEIGHT, | 659 | FIMC_CAMIF_MAX_HEIGHT, |
637 | fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1, | 660 | fimc_fmt_is_user_defined(ffmt->color) ? |
661 | 3 : 1, | ||
638 | 0); | 662 | 0); |
639 | return ffmt; | 663 | return ffmt; |
640 | } | 664 | } |
641 | /* Can't scale or crop in transparent (JPEG) transfer mode */ | 665 | /* Can't scale or crop in transparent (JPEG) transfer mode */ |
642 | if (fimc_fmt_is_jpeg(ffmt->color)) { | 666 | if (fimc_fmt_is_user_defined(ffmt->color)) { |
643 | *width = ctx->s_frame.f_width; | 667 | *width = ctx->s_frame.f_width; |
644 | *height = ctx->s_frame.f_height; | 668 | *height = ctx->s_frame.f_height; |
645 | return ffmt; | 669 | return ffmt; |
@@ -684,7 +708,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx, | |||
684 | u32 max_sc_h, max_sc_v; | 708 | u32 max_sc_h, max_sc_v; |
685 | 709 | ||
686 | /* In JPEG transparent transfer mode cropping is not supported */ | 710 | /* In JPEG transparent transfer mode cropping is not supported */ |
687 | if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) { | 711 | if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) { |
688 | r->width = sink->f_width; | 712 | r->width = sink->f_width; |
689 | r->height = sink->f_height; | 713 | r->height = sink->f_height; |
690 | r->left = r->top = 0; | 714 | r->left = r->top = 0; |
@@ -847,6 +871,48 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, | |||
847 | return 0; | 871 | return 0; |
848 | } | 872 | } |
849 | 873 | ||
874 | /** | ||
875 | * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters | ||
876 | * @sensor: pointer to the sensor subdev | ||
877 | * @plane_fmt: provides plane sizes corresponding to the frame layout entries | ||
878 | * @try: true to set the frame parameters, false to query only | ||
879 | * | ||
880 | * This function is used by this driver only for compressed/blob data formats. | ||
881 | */ | ||
882 | static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor, | ||
883 | struct v4l2_plane_pix_format *plane_fmt, | ||
884 | unsigned int num_planes, bool try) | ||
885 | { | ||
886 | struct v4l2_mbus_frame_desc fd; | ||
887 | int i, ret; | ||
888 | |||
889 | for (i = 0; i < num_planes; i++) | ||
890 | fd.entry[i].length = plane_fmt[i].sizeimage; | ||
891 | |||
892 | if (try) | ||
893 | ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd); | ||
894 | else | ||
895 | ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd); | ||
896 | |||
897 | if (ret < 0) | ||
898 | return ret; | ||
899 | |||
900 | if (num_planes != fd.num_entries) | ||
901 | return -EINVAL; | ||
902 | |||
903 | for (i = 0; i < num_planes; i++) | ||
904 | plane_fmt[i].sizeimage = fd.entry[i].length; | ||
905 | |||
906 | if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) { | ||
907 | v4l2_err(sensor->v4l2_dev, "Unsupported buffer size: %u\n", | ||
908 | fd.entry[0].length); | ||
909 | |||
910 | return -EINVAL; | ||
911 | } | ||
912 | |||
913 | return 0; | ||
914 | } | ||
915 | |||
850 | static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, | 916 | static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, |
851 | struct v4l2_format *f) | 917 | struct v4l2_format *f) |
852 | { | 918 | { |
@@ -865,7 +931,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | |||
865 | struct v4l2_mbus_framefmt mf; | 931 | struct v4l2_mbus_framefmt mf; |
866 | struct fimc_fmt *ffmt = NULL; | 932 | struct fimc_fmt *ffmt = NULL; |
867 | 933 | ||
868 | if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { | 934 | if (fimc_jpeg_fourcc(pix->pixelformat)) { |
869 | fimc_capture_try_format(ctx, &pix->width, &pix->height, | 935 | fimc_capture_try_format(ctx, &pix->width, &pix->height, |
870 | NULL, &pix->pixelformat, | 936 | NULL, &pix->pixelformat, |
871 | FIMC_SD_PAD_SINK); | 937 | FIMC_SD_PAD_SINK); |
@@ -879,25 +945,32 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, | |||
879 | return -EINVAL; | 945 | return -EINVAL; |
880 | 946 | ||
881 | if (!fimc->vid_cap.user_subdev_api) { | 947 | if (!fimc->vid_cap.user_subdev_api) { |
882 | mf.width = pix->width; | 948 | mf.width = pix->width; |
883 | mf.height = pix->height; | 949 | mf.height = pix->height; |
884 | mf.code = ffmt->mbus_code; | 950 | mf.code = ffmt->mbus_code; |
885 | fimc_md_graph_lock(fimc); | 951 | fimc_md_graph_lock(fimc); |
886 | fimc_pipeline_try_format(ctx, &mf, &ffmt, false); | 952 | fimc_pipeline_try_format(ctx, &mf, &ffmt, false); |
887 | fimc_md_graph_unlock(fimc); | 953 | fimc_md_graph_unlock(fimc); |
888 | 954 | pix->width = mf.width; | |
889 | pix->width = mf.width; | 955 | pix->height = mf.height; |
890 | pix->height = mf.height; | ||
891 | if (ffmt) | 956 | if (ffmt) |
892 | pix->pixelformat = ffmt->fourcc; | 957 | pix->pixelformat = ffmt->fourcc; |
893 | } | 958 | } |
894 | 959 | ||
895 | fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); | 960 | fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); |
961 | |||
962 | if (ffmt->flags & FMT_FLAGS_COMPRESSED) | ||
963 | fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], | ||
964 | pix->plane_fmt, ffmt->memplanes, true); | ||
965 | |||
896 | return 0; | 966 | return 0; |
897 | } | 967 | } |
898 | 968 | ||
899 | static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg) | 969 | static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, |
970 | enum fimc_color_fmt color) | ||
900 | { | 971 | { |
972 | bool jpeg = fimc_fmt_is_user_defined(color); | ||
973 | |||
901 | ctx->scaler.enabled = !jpeg; | 974 | ctx->scaler.enabled = !jpeg; |
902 | fimc_ctrls_activate(ctx, !jpeg); | 975 | fimc_ctrls_activate(ctx, !jpeg); |
903 | 976 | ||
@@ -920,7 +993,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) | |||
920 | return -EBUSY; | 993 | return -EBUSY; |
921 | 994 | ||
922 | /* Pre-configure format at camera interface input, for JPEG only */ | 995 | /* Pre-configure format at camera interface input, for JPEG only */ |
923 | if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { | 996 | if (fimc_jpeg_fourcc(pix->pixelformat)) { |
924 | fimc_capture_try_format(ctx, &pix->width, &pix->height, | 997 | fimc_capture_try_format(ctx, &pix->width, &pix->height, |
925 | NULL, &pix->pixelformat, | 998 | NULL, &pix->pixelformat, |
926 | FIMC_SD_PAD_SINK); | 999 | FIMC_SD_PAD_SINK); |
@@ -953,7 +1026,16 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) | |||
953 | } | 1026 | } |
954 | 1027 | ||
955 | fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); | 1028 | fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); |
956 | for (i = 0; i < ff->fmt->colplanes; i++) | 1029 | |
1030 | if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) { | ||
1031 | ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], | ||
1032 | pix->plane_fmt, ff->fmt->memplanes, | ||
1033 | true); | ||
1034 | if (ret < 0) | ||
1035 | return ret; | ||
1036 | } | ||
1037 | |||
1038 | for (i = 0; i < ff->fmt->memplanes; i++) | ||
957 | ff->payload[i] = pix->plane_fmt[i].sizeimage; | 1039 | ff->payload[i] = pix->plane_fmt[i].sizeimage; |
958 | 1040 | ||
959 | set_frame_bounds(ff, pix->width, pix->height); | 1041 | 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) | |||
961 | if (!(ctx->state & FIMC_COMPOSE)) | 1043 | if (!(ctx->state & FIMC_COMPOSE)) |
962 | set_frame_crop(ff, 0, 0, pix->width, pix->height); | 1044 | set_frame_crop(ff, 0, 0, pix->width, pix->height); |
963 | 1045 | ||
964 | fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color)); | 1046 | fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color); |
965 | 1047 | ||
966 | /* Reset cropping and set format at the camera interface input */ | 1048 | /* Reset cropping and set format at the camera interface input */ |
967 | if (!fimc->vid_cap.user_subdev_api) { | 1049 | if (!fimc->vid_cap.user_subdev_api) { |
@@ -1063,6 +1145,23 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) | |||
1063 | src_fmt.format.height != sink_fmt.format.height || | 1145 | src_fmt.format.height != sink_fmt.format.height || |
1064 | src_fmt.format.code != sink_fmt.format.code) | 1146 | src_fmt.format.code != sink_fmt.format.code) |
1065 | return -EPIPE; | 1147 | return -EPIPE; |
1148 | |||
1149 | if (sd == fimc->pipeline.subdevs[IDX_SENSOR] && | ||
1150 | fimc_user_defined_mbus_fmt(src_fmt.format.code)) { | ||
1151 | struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES]; | ||
1152 | struct fimc_frame *frame = &vid_cap->ctx->d_frame; | ||
1153 | unsigned int i; | ||
1154 | |||
1155 | ret = fimc_get_sensor_frame_desc(sd, plane_fmt, | ||
1156 | frame->fmt->memplanes, | ||
1157 | false); | ||
1158 | if (ret < 0) | ||
1159 | return -EPIPE; | ||
1160 | |||
1161 | for (i = 0; i < frame->fmt->memplanes; i++) | ||
1162 | if (frame->payload[i] < plane_fmt[i].sizeimage) | ||
1163 | return -EPIPE; | ||
1164 | } | ||
1066 | } | 1165 | } |
1067 | return 0; | 1166 | return 0; |
1068 | } | 1167 | } |
@@ -1424,7 +1523,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd, | |||
1424 | /* Update RGB Alpha control state and value range */ | 1523 | /* Update RGB Alpha control state and value range */ |
1425 | fimc_alpha_ctrl_update(ctx); | 1524 | fimc_alpha_ctrl_update(ctx); |
1426 | 1525 | ||
1427 | fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color)); | 1526 | fimc_capture_mark_jpeg_xfer(ctx, ffmt->color); |
1428 | 1527 | ||
1429 | ff = fmt->pad == FIMC_SD_PAD_SINK ? | 1528 | ff = fmt->pad == FIMC_SD_PAD_SINK ? |
1430 | &ctx->s_frame : &ctx->d_frame; | 1529 | &ctx->s_frame : &ctx->d_frame; |
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c index 1a445404e73d..8d0d2b94a135 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.c +++ b/drivers/media/platform/s5p-fimc/fimc-core.c | |||
@@ -184,7 +184,17 @@ static struct fimc_fmt fimc_formats[] = { | |||
184 | .memplanes = 1, | 184 | .memplanes = 1, |
185 | .colplanes = 1, | 185 | .colplanes = 1, |
186 | .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, | 186 | .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, |
187 | .flags = FMT_FLAGS_CAM, | 187 | .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED, |
188 | }, { | ||
189 | .name = "S5C73MX interleaved UYVY/JPEG", | ||
190 | .fourcc = V4L2_PIX_FMT_S5C_UYVY_JPG, | ||
191 | .color = FIMC_FMT_YUYV_JPEG, | ||
192 | .depth = { 8 }, | ||
193 | .memplanes = 2, | ||
194 | .colplanes = 1, | ||
195 | .mdataplanes = 0x2, /* plane 1 holds frame meta data */ | ||
196 | .mbus_code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8, | ||
197 | .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED, | ||
188 | }, | 198 | }, |
189 | }; | 199 | }; |
190 | 200 | ||
@@ -371,7 +381,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, | |||
371 | default: | 381 | default: |
372 | return -EINVAL; | 382 | return -EINVAL; |
373 | } | 383 | } |
374 | } else { | 384 | } else if (!frame->fmt->mdataplanes) { |
375 | if (frame->fmt->memplanes >= 2) | 385 | if (frame->fmt->memplanes >= 2) |
376 | paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1); | 386 | paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1); |
377 | 387 | ||
@@ -698,6 +708,11 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f) | |||
698 | if (frame->fmt->colplanes == 1) /* packed formats */ | 708 | if (frame->fmt->colplanes == 1) /* packed formats */ |
699 | bpl = (bpl * frame->fmt->depth[0]) / 8; | 709 | bpl = (bpl * frame->fmt->depth[0]) / 8; |
700 | pixm->plane_fmt[i].bytesperline = bpl; | 710 | pixm->plane_fmt[i].bytesperline = bpl; |
711 | |||
712 | if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) { | ||
713 | pixm->plane_fmt[i].sizeimage = frame->payload[i]; | ||
714 | continue; | ||
715 | } | ||
701 | pixm->plane_fmt[i].sizeimage = (frame->o_width * | 716 | pixm->plane_fmt[i].sizeimage = (frame->o_width * |
702 | frame->o_height * frame->fmt->depth[i]) / 8; | 717 | frame->o_height * frame->fmt->depth[i]) / 8; |
703 | } | 718 | } |
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h index cd716ba6015f..c0040d792499 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.h +++ b/drivers/media/platform/s5p-fimc/fimc-core.h | |||
@@ -40,6 +40,8 @@ | |||
40 | #define SCALER_MAX_VRATIO 64 | 40 | #define SCALER_MAX_VRATIO 64 |
41 | #define DMA_MIN_SIZE 8 | 41 | #define DMA_MIN_SIZE 8 |
42 | #define FIMC_CAMIF_MAX_HEIGHT 0x2000 | 42 | #define FIMC_CAMIF_MAX_HEIGHT 0x2000 |
43 | #define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M) | ||
44 | #define FIMC_MAX_PLANES 3 | ||
43 | 45 | ||
44 | /* indices to the clocks array */ | 46 | /* indices to the clocks array */ |
45 | enum { | 47 | enum { |
@@ -83,7 +85,7 @@ enum fimc_datapath { | |||
83 | }; | 85 | }; |
84 | 86 | ||
85 | enum fimc_color_fmt { | 87 | enum fimc_color_fmt { |
86 | FIMC_FMT_RGB444 = 0x10, | 88 | FIMC_FMT_RGB444 = 0x10, |
87 | FIMC_FMT_RGB555, | 89 | FIMC_FMT_RGB555, |
88 | FIMC_FMT_RGB565, | 90 | FIMC_FMT_RGB565, |
89 | FIMC_FMT_RGB666, | 91 | FIMC_FMT_RGB666, |
@@ -95,14 +97,15 @@ enum fimc_color_fmt { | |||
95 | FIMC_FMT_CBYCRY422, | 97 | FIMC_FMT_CBYCRY422, |
96 | FIMC_FMT_CRYCBY422, | 98 | FIMC_FMT_CRYCBY422, |
97 | FIMC_FMT_YCBCR444_LOCAL, | 99 | FIMC_FMT_YCBCR444_LOCAL, |
98 | FIMC_FMT_JPEG = 0x40, | 100 | FIMC_FMT_RAW8 = 0x40, |
99 | FIMC_FMT_RAW8 = 0x80, | ||
100 | FIMC_FMT_RAW10, | 101 | FIMC_FMT_RAW10, |
101 | FIMC_FMT_RAW12, | 102 | FIMC_FMT_RAW12, |
103 | FIMC_FMT_JPEG = 0x80, | ||
104 | FIMC_FMT_YUYV_JPEG = 0x100, | ||
102 | }; | 105 | }; |
103 | 106 | ||
107 | #define fimc_fmt_is_user_defined(x) (!!((x) & 0x180)) | ||
104 | #define fimc_fmt_is_rgb(x) (!!((x) & 0x10)) | 108 | #define fimc_fmt_is_rgb(x) (!!((x) & 0x10)) |
105 | #define fimc_fmt_is_jpeg(x) (!!((x) & 0x40)) | ||
106 | 109 | ||
107 | #define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \ | 110 | #define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \ |
108 | __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | 111 | __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
@@ -139,6 +142,7 @@ enum fimc_color_fmt { | |||
139 | * @memplanes: number of physically non-contiguous data planes | 142 | * @memplanes: number of physically non-contiguous data planes |
140 | * @colplanes: number of physically contiguous data planes | 143 | * @colplanes: number of physically contiguous data planes |
141 | * @depth: per plane driver's private 'number of bits per pixel' | 144 | * @depth: per plane driver's private 'number of bits per pixel' |
145 | * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no) | ||
142 | * @flags: flags indicating which operation mode format applies to | 146 | * @flags: flags indicating which operation mode format applies to |
143 | */ | 147 | */ |
144 | struct fimc_fmt { | 148 | struct fimc_fmt { |
@@ -149,12 +153,14 @@ struct fimc_fmt { | |||
149 | u16 memplanes; | 153 | u16 memplanes; |
150 | u16 colplanes; | 154 | u16 colplanes; |
151 | u8 depth[VIDEO_MAX_PLANES]; | 155 | u8 depth[VIDEO_MAX_PLANES]; |
156 | u16 mdataplanes; | ||
152 | u16 flags; | 157 | u16 flags; |
153 | #define FMT_FLAGS_CAM (1 << 0) | 158 | #define FMT_FLAGS_CAM (1 << 0) |
154 | #define FMT_FLAGS_M2M_IN (1 << 1) | 159 | #define FMT_FLAGS_M2M_IN (1 << 1) |
155 | #define FMT_FLAGS_M2M_OUT (1 << 2) | 160 | #define FMT_FLAGS_M2M_OUT (1 << 2) |
156 | #define FMT_FLAGS_M2M (1 << 1 | 1 << 2) | 161 | #define FMT_FLAGS_M2M (1 << 1 | 1 << 2) |
157 | #define FMT_HAS_ALPHA (1 << 3) | 162 | #define FMT_HAS_ALPHA (1 << 3) |
163 | #define FMT_FLAGS_COMPRESSED (1 << 4) | ||
158 | }; | 164 | }; |
159 | 165 | ||
160 | /** | 166 | /** |
@@ -272,7 +278,7 @@ struct fimc_frame { | |||
272 | u32 offs_v; | 278 | u32 offs_v; |
273 | u32 width; | 279 | u32 width; |
274 | u32 height; | 280 | u32 height; |
275 | unsigned long payload[VIDEO_MAX_PLANES]; | 281 | unsigned int payload[VIDEO_MAX_PLANES]; |
276 | struct fimc_addr paddr; | 282 | struct fimc_addr paddr; |
277 | struct fimc_dma_offset dma_offset; | 283 | struct fimc_dma_offset dma_offset; |
278 | struct fimc_fmt *fmt; | 284 | struct fimc_fmt *fmt; |
@@ -577,6 +583,18 @@ static inline int tiled_fmt(struct fimc_fmt *fmt) | |||
577 | return fmt->fourcc == V4L2_PIX_FMT_NV12MT; | 583 | return fmt->fourcc == V4L2_PIX_FMT_NV12MT; |
578 | } | 584 | } |
579 | 585 | ||
586 | static inline bool fimc_jpeg_fourcc(u32 pixelformat) | ||
587 | { | ||
588 | return (pixelformat == V4L2_PIX_FMT_JPEG || | ||
589 | pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG); | ||
590 | } | ||
591 | |||
592 | static inline bool fimc_user_defined_mbus_fmt(u32 code) | ||
593 | { | ||
594 | return (code == V4L2_MBUS_FMT_JPEG_1X8 || | ||
595 | code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8); | ||
596 | } | ||
597 | |||
580 | /* Return the alpha component bit mask */ | 598 | /* Return the alpha component bit mask */ |
581 | static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) | 599 | static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) |
582 | { | 600 | { |
diff --git a/drivers/media/platform/s5p-fimc/fimc-m2m.c b/drivers/media/platform/s5p-fimc/fimc-m2m.c index 6b71d953fd15..4500e44f6857 100644 --- a/drivers/media/platform/s5p-fimc/fimc-m2m.c +++ b/drivers/media/platform/s5p-fimc/fimc-m2m.c | |||
@@ -551,30 +551,31 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) | |||
551 | return 0; | 551 | return 0; |
552 | } | 552 | } |
553 | 553 | ||
554 | static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr) | 554 | static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop) |
555 | { | 555 | { |
556 | struct fimc_ctx *ctx = fh_to_ctx(fh); | 556 | struct fimc_ctx *ctx = fh_to_ctx(fh); |
557 | struct fimc_dev *fimc = ctx->fimc_dev; | 557 | struct fimc_dev *fimc = ctx->fimc_dev; |
558 | struct v4l2_crop cr = *crop; | ||
558 | struct fimc_frame *f; | 559 | struct fimc_frame *f; |
559 | int ret; | 560 | int ret; |
560 | 561 | ||
561 | ret = fimc_m2m_try_crop(ctx, cr); | 562 | ret = fimc_m2m_try_crop(ctx, &cr); |
562 | if (ret) | 563 | if (ret) |
563 | return ret; | 564 | return ret; |
564 | 565 | ||
565 | f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? | 566 | f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? |
566 | &ctx->s_frame : &ctx->d_frame; | 567 | &ctx->s_frame : &ctx->d_frame; |
567 | 568 | ||
568 | /* Check to see if scaling ratio is within supported range */ | 569 | /* Check to see if scaling ratio is within supported range */ |
569 | if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) { | 570 | if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) { |
570 | if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 571 | if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
571 | ret = fimc_check_scaler_ratio(ctx, cr->c.width, | 572 | ret = fimc_check_scaler_ratio(ctx, cr.c.width, |
572 | cr->c.height, ctx->d_frame.width, | 573 | cr.c.height, ctx->d_frame.width, |
573 | ctx->d_frame.height, ctx->rotation); | 574 | ctx->d_frame.height, ctx->rotation); |
574 | } else { | 575 | } else { |
575 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, | 576 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, |
576 | ctx->s_frame.height, cr->c.width, | 577 | ctx->s_frame.height, cr.c.width, |
577 | cr->c.height, ctx->rotation); | 578 | cr.c.height, ctx->rotation); |
578 | } | 579 | } |
579 | if (ret) { | 580 | if (ret) { |
580 | v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); | 581 | 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 * | |||
582 | } | 583 | } |
583 | } | 584 | } |
584 | 585 | ||
585 | f->offs_h = cr->c.left; | 586 | f->offs_h = cr.c.left; |
586 | f->offs_v = cr->c.top; | 587 | f->offs_v = cr.c.top; |
587 | f->width = cr->c.width; | 588 | f->width = cr.c.width; |
588 | f->height = cr->c.height; | 589 | f->height = cr.c.height; |
589 | 590 | ||
590 | fimc_ctx_state_set(FIMC_PARAMS, ctx); | 591 | fimc_ctx_state_set(FIMC_PARAMS, ctx); |
591 | 592 | ||
diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.c b/drivers/media/platform/s5p-fimc/fimc-reg.c index 783408fd7d56..2c9d0c06c9e8 100644 --- a/drivers/media/platform/s5p-fimc/fimc-reg.c +++ b/drivers/media/platform/s5p-fimc/fimc-reg.c | |||
@@ -625,7 +625,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc, | |||
625 | cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; | 625 | cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; |
626 | } /* else defaults to ITU-R BT.656 8-bit */ | 626 | } /* else defaults to ITU-R BT.656 8-bit */ |
627 | } else if (cam->bus_type == FIMC_MIPI_CSI2) { | 627 | } else if (cam->bus_type == FIMC_MIPI_CSI2) { |
628 | if (fimc_fmt_is_jpeg(f->fmt->color)) | 628 | if (fimc_fmt_is_user_defined(f->fmt->color)) |
629 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; | 629 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; |
630 | } | 630 | } |
631 | 631 | ||
@@ -680,6 +680,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, | |||
680 | tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT; | 680 | tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT; |
681 | break; | 681 | break; |
682 | case V4L2_MBUS_FMT_JPEG_1X8: | 682 | case V4L2_MBUS_FMT_JPEG_1X8: |
683 | case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8: | ||
683 | tmp = FIMC_REG_CSIIMGFMT_USER(1); | 684 | tmp = FIMC_REG_CSIIMGFMT_USER(1); |
684 | cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; | 685 | cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; |
685 | break; | 686 | break; |
@@ -744,13 +745,13 @@ void fimc_hw_dis_capture(struct fimc_dev *dev) | |||
744 | } | 745 | } |
745 | 746 | ||
746 | /* Return an index to the buffer actually being written. */ | 747 | /* Return an index to the buffer actually being written. */ |
747 | u32 fimc_hw_get_frame_index(struct fimc_dev *dev) | 748 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev) |
748 | { | 749 | { |
749 | u32 reg; | 750 | s32 reg; |
750 | 751 | ||
751 | if (dev->variant->has_cistatus2) { | 752 | if (dev->variant->has_cistatus2) { |
752 | reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F; | 753 | reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f; |
753 | return reg > 0 ? --reg : reg; | 754 | return reg - 1; |
754 | } | 755 | } |
755 | 756 | ||
756 | reg = readl(dev->regs + FIMC_REG_CISTATUS); | 757 | reg = readl(dev->regs + FIMC_REG_CISTATUS); |
@@ -759,6 +760,18 @@ u32 fimc_hw_get_frame_index(struct fimc_dev *dev) | |||
759 | FIMC_REG_CISTATUS_FRAMECNT_SHIFT; | 760 | FIMC_REG_CISTATUS_FRAMECNT_SHIFT; |
760 | } | 761 | } |
761 | 762 | ||
763 | /* Return an index to the buffer being written previously. */ | ||
764 | s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev) | ||
765 | { | ||
766 | s32 reg; | ||
767 | |||
768 | if (!dev->variant->has_cistatus2) | ||
769 | return -1; | ||
770 | |||
771 | reg = readl(dev->regs + FIMC_REG_CISTATUS2); | ||
772 | return ((reg >> 7) & 0x3f) - 1; | ||
773 | } | ||
774 | |||
762 | /* Locking: the caller holds fimc->slock */ | 775 | /* Locking: the caller holds fimc->slock */ |
763 | void fimc_activate_capture(struct fimc_ctx *ctx) | 776 | void fimc_activate_capture(struct fimc_ctx *ctx) |
764 | { | 777 | { |
diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.h b/drivers/media/platform/s5p-fimc/fimc-reg.h index 579ac8ac03de..b6abfc7b72ac 100644 --- a/drivers/media/platform/s5p-fimc/fimc-reg.h +++ b/drivers/media/platform/s5p-fimc/fimc-reg.h | |||
@@ -307,7 +307,8 @@ void fimc_hw_clear_irq(struct fimc_dev *dev); | |||
307 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); | 307 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); |
308 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); | 308 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); |
309 | void fimc_hw_dis_capture(struct fimc_dev *dev); | 309 | void fimc_hw_dis_capture(struct fimc_dev *dev); |
310 | u32 fimc_hw_get_frame_index(struct fimc_dev *dev); | 310 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev); |
311 | s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev); | ||
311 | void fimc_activate_capture(struct fimc_ctx *ctx); | 312 | void fimc_activate_capture(struct fimc_ctx *ctx); |
312 | void fimc_deactivate_capture(struct fimc_dev *fimc); | 313 | void fimc_deactivate_capture(struct fimc_dev *fimc); |
313 | 314 | ||
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c index e92236ac5cfe..4c961b1b68e6 100644 --- a/drivers/media/platform/s5p-fimc/mipi-csis.c +++ b/drivers/media/platform/s5p-fimc/mipi-csis.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver | 2 | * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. | 4 | * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. |
5 | * Sylwester Nawrocki, <s.nawrocki@samsung.com> | 5 | * Sylwester Nawrocki <s.nawrocki@samsung.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * 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)"); | |||
98 | #define CSIS_MAX_PIX_WIDTH 0xffff | 98 | #define CSIS_MAX_PIX_WIDTH 0xffff |
99 | #define CSIS_MAX_PIX_HEIGHT 0xffff | 99 | #define CSIS_MAX_PIX_HEIGHT 0xffff |
100 | 100 | ||
101 | /* Non-image packet data buffers */ | ||
102 | #define S5PCSIS_PKTDATA_ODD 0x2000 | ||
103 | #define S5PCSIS_PKTDATA_EVEN 0x3000 | ||
104 | #define S5PCSIS_PKTDATA_SIZE SZ_4K | ||
105 | |||
101 | enum { | 106 | enum { |
102 | CSIS_CLK_MUX, | 107 | CSIS_CLK_MUX, |
103 | CSIS_CLK_GATE, | 108 | CSIS_CLK_GATE, |
@@ -110,8 +115,8 @@ static char *csi_clock_name[] = { | |||
110 | #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name) | 115 | #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name) |
111 | 116 | ||
112 | static const char * const csis_supply_name[] = { | 117 | static const char * const csis_supply_name[] = { |
113 | "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */ | 118 | "vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */ |
114 | "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */ | 119 | "vddio", /* CSIS I/O and PLL (1.8V) supply */ |
115 | }; | 120 | }; |
116 | #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name) | 121 | #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name) |
117 | 122 | ||
@@ -144,12 +149,18 @@ static const struct s5pcsis_event s5pcsis_events[] = { | |||
144 | }; | 149 | }; |
145 | #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) | 150 | #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) |
146 | 151 | ||
152 | struct csis_pktbuf { | ||
153 | u32 *data; | ||
154 | unsigned int len; | ||
155 | }; | ||
156 | |||
147 | /** | 157 | /** |
148 | * struct csis_state - the driver's internal state data structure | 158 | * struct csis_state - the driver's internal state data structure |
149 | * @lock: mutex serializing the subdev and power management operations, | 159 | * @lock: mutex serializing the subdev and power management operations, |
150 | * protecting @format and @flags members | 160 | * protecting @format and @flags members |
151 | * @pads: CSIS pads array | 161 | * @pads: CSIS pads array |
152 | * @sd: v4l2_subdev associated with CSIS device instance | 162 | * @sd: v4l2_subdev associated with CSIS device instance |
163 | * @index: the hardware instance index | ||
153 | * @pdev: CSIS platform device | 164 | * @pdev: CSIS platform device |
154 | * @regs: mmaped I/O registers memory | 165 | * @regs: mmaped I/O registers memory |
155 | * @supplies: CSIS regulator supplies | 166 | * @supplies: CSIS regulator supplies |
@@ -159,12 +170,14 @@ static const struct s5pcsis_event s5pcsis_events[] = { | |||
159 | * @csis_fmt: current CSIS pixel format | 170 | * @csis_fmt: current CSIS pixel format |
160 | * @format: common media bus format for the source and sink pad | 171 | * @format: common media bus format for the source and sink pad |
161 | * @slock: spinlock protecting structure members below | 172 | * @slock: spinlock protecting structure members below |
173 | * @pkt_buf: the frame embedded (non-image) data buffer | ||
162 | * @events: MIPI-CSIS event (error) counters | 174 | * @events: MIPI-CSIS event (error) counters |
163 | */ | 175 | */ |
164 | struct csis_state { | 176 | struct csis_state { |
165 | struct mutex lock; | 177 | struct mutex lock; |
166 | struct media_pad pads[CSIS_PADS_NUM]; | 178 | struct media_pad pads[CSIS_PADS_NUM]; |
167 | struct v4l2_subdev sd; | 179 | struct v4l2_subdev sd; |
180 | u8 index; | ||
168 | struct platform_device *pdev; | 181 | struct platform_device *pdev; |
169 | void __iomem *regs; | 182 | void __iomem *regs; |
170 | struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; | 183 | struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; |
@@ -175,6 +188,7 @@ struct csis_state { | |||
175 | struct v4l2_mbus_framefmt format; | 188 | struct v4l2_mbus_framefmt format; |
176 | 189 | ||
177 | struct spinlock slock; | 190 | struct spinlock slock; |
191 | struct csis_pktbuf pkt_buf; | ||
178 | struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; | 192 | struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; |
179 | }; | 193 | }; |
180 | 194 | ||
@@ -202,7 +216,11 @@ static const struct csis_pix_format s5pcsis_formats[] = { | |||
202 | .code = V4L2_MBUS_FMT_JPEG_1X8, | 216 | .code = V4L2_MBUS_FMT_JPEG_1X8, |
203 | .fmt_reg = S5PCSIS_CFG_FMT_USER(1), | 217 | .fmt_reg = S5PCSIS_CFG_FMT_USER(1), |
204 | .data_alignment = 32, | 218 | .data_alignment = 32, |
205 | }, | 219 | }, { |
220 | .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8, | ||
221 | .fmt_reg = S5PCSIS_CFG_FMT_USER(1), | ||
222 | .data_alignment = 32, | ||
223 | } | ||
206 | }; | 224 | }; |
207 | 225 | ||
208 | #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r) | 226 | #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r) |
@@ -266,7 +284,7 @@ static void __s5pcsis_set_format(struct csis_state *state) | |||
266 | struct v4l2_mbus_framefmt *mf = &state->format; | 284 | struct v4l2_mbus_framefmt *mf = &state->format; |
267 | u32 val; | 285 | u32 val; |
268 | 286 | ||
269 | v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n", | 287 | v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n", |
270 | mf->code, mf->width, mf->height); | 288 | mf->code, mf->width, mf->height); |
271 | 289 | ||
272 | /* Color format */ | 290 | /* Color format */ |
@@ -304,8 +322,10 @@ static void s5pcsis_set_params(struct csis_state *state) | |||
304 | val |= S5PCSIS_CTRL_ALIGN_32BIT; | 322 | val |= S5PCSIS_CTRL_ALIGN_32BIT; |
305 | else /* 24-bits */ | 323 | else /* 24-bits */ |
306 | val &= ~S5PCSIS_CTRL_ALIGN_32BIT; | 324 | val &= ~S5PCSIS_CTRL_ALIGN_32BIT; |
307 | /* Not using external clock. */ | 325 | |
308 | val &= ~S5PCSIS_CTRL_WCLK_EXTCLK; | 326 | val &= ~S5PCSIS_CTRL_WCLK_EXTCLK; |
327 | if (pdata->wclk_source) | ||
328 | val |= S5PCSIS_CTRL_WCLK_EXTCLK; | ||
309 | s5pcsis_write(state, S5PCSIS_CTRL, val); | 329 | s5pcsis_write(state, S5PCSIS_CTRL, val); |
310 | 330 | ||
311 | /* Update the shadow register. */ | 331 | /* Update the shadow register. */ |
@@ -529,6 +549,22 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
529 | return 0; | 549 | return 0; |
530 | } | 550 | } |
531 | 551 | ||
552 | static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf, | ||
553 | unsigned int *size) | ||
554 | { | ||
555 | struct csis_state *state = sd_to_csis_state(sd); | ||
556 | unsigned long flags; | ||
557 | |||
558 | *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE); | ||
559 | |||
560 | spin_lock_irqsave(&state->slock, flags); | ||
561 | state->pkt_buf.data = buf; | ||
562 | state->pkt_buf.len = *size; | ||
563 | spin_unlock_irqrestore(&state->slock, flags); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
532 | static int s5pcsis_log_status(struct v4l2_subdev *sd) | 568 | static int s5pcsis_log_status(struct v4l2_subdev *sd) |
533 | { | 569 | { |
534 | struct csis_state *state = sd_to_csis_state(sd); | 570 | struct csis_state *state = sd_to_csis_state(sd); |
@@ -566,6 +602,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = { | |||
566 | }; | 602 | }; |
567 | 603 | ||
568 | static struct v4l2_subdev_video_ops s5pcsis_video_ops = { | 604 | static struct v4l2_subdev_video_ops s5pcsis_video_ops = { |
605 | .s_rx_buffer = s5pcsis_s_rx_buffer, | ||
569 | .s_stream = s5pcsis_s_stream, | 606 | .s_stream = s5pcsis_s_stream, |
570 | }; | 607 | }; |
571 | 608 | ||
@@ -578,13 +615,26 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = { | |||
578 | static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) | 615 | static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) |
579 | { | 616 | { |
580 | struct csis_state *state = dev_id; | 617 | struct csis_state *state = dev_id; |
618 | struct csis_pktbuf *pktbuf = &state->pkt_buf; | ||
581 | unsigned long flags; | 619 | unsigned long flags; |
582 | u32 status; | 620 | u32 status; |
583 | 621 | ||
584 | status = s5pcsis_read(state, S5PCSIS_INTSRC); | 622 | status = s5pcsis_read(state, S5PCSIS_INTSRC); |
585 | |||
586 | spin_lock_irqsave(&state->slock, flags); | 623 | spin_lock_irqsave(&state->slock, flags); |
587 | 624 | ||
625 | if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) { | ||
626 | u32 offset; | ||
627 | |||
628 | if (status & S5PCSIS_INTSRC_EVEN) | ||
629 | offset = S5PCSIS_PKTDATA_EVEN; | ||
630 | else | ||
631 | offset = S5PCSIS_PKTDATA_ODD; | ||
632 | |||
633 | memcpy(pktbuf->data, state->regs + offset, pktbuf->len); | ||
634 | pktbuf->data = NULL; | ||
635 | rmb(); | ||
636 | } | ||
637 | |||
588 | /* Update the event/error counters */ | 638 | /* Update the event/error counters */ |
589 | if ((status & S5PCSIS_INTSRC_ERRORS) || debug) { | 639 | if ((status & S5PCSIS_INTSRC_ERRORS) || debug) { |
590 | int i; | 640 | int i; |
@@ -620,14 +670,15 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
620 | spin_lock_init(&state->slock); | 670 | spin_lock_init(&state->slock); |
621 | 671 | ||
622 | state->pdev = pdev; | 672 | state->pdev = pdev; |
673 | state->index = max(0, pdev->id); | ||
623 | 674 | ||
624 | pdata = pdev->dev.platform_data; | 675 | pdata = pdev->dev.platform_data; |
625 | if (pdata == NULL || pdata->phy_enable == NULL) { | 676 | if (pdata == NULL) { |
626 | dev_err(&pdev->dev, "Platform data not fully specified\n"); | 677 | dev_err(&pdev->dev, "Platform data not fully specified\n"); |
627 | return -EINVAL; | 678 | return -EINVAL; |
628 | } | 679 | } |
629 | 680 | ||
630 | if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || | 681 | if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) || |
631 | pdata->lanes > CSIS0_MAX_LANES) { | 682 | pdata->lanes > CSIS0_MAX_LANES) { |
632 | dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", | 683 | dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", |
633 | pdata->lanes); | 684 | pdata->lanes); |
@@ -710,7 +761,6 @@ e_clkput: | |||
710 | 761 | ||
711 | static int s5pcsis_pm_suspend(struct device *dev, bool runtime) | 762 | static int s5pcsis_pm_suspend(struct device *dev, bool runtime) |
712 | { | 763 | { |
713 | struct s5p_platform_mipi_csis *pdata = dev->platform_data; | ||
714 | struct platform_device *pdev = to_platform_device(dev); | 764 | struct platform_device *pdev = to_platform_device(dev); |
715 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); | 765 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); |
716 | struct csis_state *state = sd_to_csis_state(sd); | 766 | struct csis_state *state = sd_to_csis_state(sd); |
@@ -722,7 +772,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime) | |||
722 | mutex_lock(&state->lock); | 772 | mutex_lock(&state->lock); |
723 | if (state->flags & ST_POWERED) { | 773 | if (state->flags & ST_POWERED) { |
724 | s5pcsis_stop_stream(state); | 774 | s5pcsis_stop_stream(state); |
725 | ret = pdata->phy_enable(state->pdev, false); | 775 | ret = s5p_csis_phy_enable(state->index, false); |
726 | if (ret) | 776 | if (ret) |
727 | goto unlock; | 777 | goto unlock; |
728 | ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES, | 778 | ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES, |
@@ -741,7 +791,6 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime) | |||
741 | 791 | ||
742 | static int s5pcsis_pm_resume(struct device *dev, bool runtime) | 792 | static int s5pcsis_pm_resume(struct device *dev, bool runtime) |
743 | { | 793 | { |
744 | struct s5p_platform_mipi_csis *pdata = dev->platform_data; | ||
745 | struct platform_device *pdev = to_platform_device(dev); | 794 | struct platform_device *pdev = to_platform_device(dev); |
746 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); | 795 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); |
747 | struct csis_state *state = sd_to_csis_state(sd); | 796 | struct csis_state *state = sd_to_csis_state(sd); |
@@ -759,7 +808,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime) | |||
759 | state->supplies); | 808 | state->supplies); |
760 | if (ret) | 809 | if (ret) |
761 | goto unlock; | 810 | goto unlock; |
762 | ret = pdata->phy_enable(state->pdev, true); | 811 | ret = s5p_csis_phy_enable(state->index, true); |
763 | if (!ret) { | 812 | if (!ret) { |
764 | state->flags |= ST_POWERED; | 813 | state->flags |= ST_POWERED; |
765 | } else { | 814 | } else { |
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 1e3b9dd014c0..1bfbc325836b 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c | |||
@@ -507,7 +507,7 @@ static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr) | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr) | 510 | static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr) |
511 | { | 511 | { |
512 | struct g2d_ctx *ctx = prv; | 512 | struct g2d_ctx *ctx = prv; |
513 | struct g2d_dev *dev = ctx->dev; | 513 | struct g2d_dev *dev = ctx->dev; |
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 394775ae5774..17983c4c9a9a 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c | |||
@@ -1353,7 +1353,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) | |||
1353 | return ret; | 1353 | return ret; |
1354 | } | 1354 | } |
1355 | dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk); | 1355 | dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk); |
1356 | clk_enable(jpeg->clk); | 1356 | clk_prepare_enable(jpeg->clk); |
1357 | 1357 | ||
1358 | /* v4l2 device */ | 1358 | /* v4l2 device */ |
1359 | ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); | 1359 | ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); |
@@ -1460,7 +1460,7 @@ device_register_rollback: | |||
1460 | v4l2_device_unregister(&jpeg->v4l2_dev); | 1460 | v4l2_device_unregister(&jpeg->v4l2_dev); |
1461 | 1461 | ||
1462 | clk_get_rollback: | 1462 | clk_get_rollback: |
1463 | clk_disable(jpeg->clk); | 1463 | clk_disable_unprepare(jpeg->clk); |
1464 | clk_put(jpeg->clk); | 1464 | clk_put(jpeg->clk); |
1465 | 1465 | ||
1466 | return ret; | 1466 | return ret; |
@@ -1480,7 +1480,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev) | |||
1480 | v4l2_m2m_release(jpeg->m2m_dev); | 1480 | v4l2_m2m_release(jpeg->m2m_dev); |
1481 | v4l2_device_unregister(&jpeg->v4l2_dev); | 1481 | v4l2_device_unregister(&jpeg->v4l2_dev); |
1482 | 1482 | ||
1483 | clk_disable(jpeg->clk); | 1483 | clk_disable_unprepare(jpeg->clk); |
1484 | clk_put(jpeg->clk); | 1484 | clk_put(jpeg->clk); |
1485 | 1485 | ||
1486 | return 0; | 1486 | return 0; |
diff --git a/drivers/media/platform/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile index d0663409af00..379008c6d09a 100644 --- a/drivers/media/platform/s5p-mfc/Makefile +++ b/drivers/media/platform/s5p-mfc/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o | 1 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o |
2 | s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o | 2 | s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o |
3 | s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o | 3 | s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o |
4 | s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o | 4 | s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o |
5 | s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o | 5 | s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o |
6 | s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o | ||
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h new file mode 100644 index 000000000000..363a97cc7681 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h | |||
@@ -0,0 +1,408 @@ | |||
1 | /* | ||
2 | * Register definition file for Samsung MFC V6.x Interface (FIMV) driver | ||
3 | * | ||
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _REGS_FIMV_V6_H | ||
13 | #define _REGS_FIMV_V6_H | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/sizes.h> | ||
17 | |||
18 | #define S5P_FIMV_REG_SIZE_V6 (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) | ||
19 | #define S5P_FIMV_REG_COUNT_V6 ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4) | ||
20 | |||
21 | /* Number of bits that the buffer address should be shifted for particular | ||
22 | * MFC buffers. */ | ||
23 | #define S5P_FIMV_MEM_OFFSET_V6 0 | ||
24 | |||
25 | #define S5P_FIMV_START_ADDR_V6 0x0000 | ||
26 | #define S5P_FIMV_END_ADDR_V6 0xfd80 | ||
27 | |||
28 | #define S5P_FIMV_REG_CLEAR_BEGIN_V6 0xf000 | ||
29 | #define S5P_FIMV_REG_CLEAR_COUNT_V6 1024 | ||
30 | |||
31 | /* Codec Common Registers */ | ||
32 | #define S5P_FIMV_RISC_ON_V6 0x0000 | ||
33 | #define S5P_FIMV_RISC2HOST_INT_V6 0x003C | ||
34 | #define S5P_FIMV_HOST2RISC_INT_V6 0x0044 | ||
35 | #define S5P_FIMV_RISC_BASE_ADDRESS_V6 0x0054 | ||
36 | |||
37 | #define S5P_FIMV_MFC_RESET_V6 0x1070 | ||
38 | |||
39 | #define S5P_FIMV_HOST2RISC_CMD_V6 0x1100 | ||
40 | #define S5P_FIMV_H2R_CMD_EMPTY_V6 0 | ||
41 | #define S5P_FIMV_H2R_CMD_SYS_INIT_V6 1 | ||
42 | #define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6 2 | ||
43 | #define S5P_FIMV_CH_SEQ_HEADER_V6 3 | ||
44 | #define S5P_FIMV_CH_INIT_BUFS_V6 4 | ||
45 | #define S5P_FIMV_CH_FRAME_START_V6 5 | ||
46 | #define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6 6 | ||
47 | #define S5P_FIMV_H2R_CMD_SLEEP_V6 7 | ||
48 | #define S5P_FIMV_H2R_CMD_WAKEUP_V6 8 | ||
49 | #define S5P_FIMV_CH_LAST_FRAME_V6 9 | ||
50 | #define S5P_FIMV_H2R_CMD_FLUSH_V6 10 | ||
51 | /* RMVME: REALLOC used? */ | ||
52 | #define S5P_FIMV_CH_FRAME_START_REALLOC_V6 5 | ||
53 | |||
54 | #define S5P_FIMV_RISC2HOST_CMD_V6 0x1104 | ||
55 | #define S5P_FIMV_R2H_CMD_EMPTY_V6 0 | ||
56 | #define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6 1 | ||
57 | #define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6 2 | ||
58 | #define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6 3 | ||
59 | #define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6 4 | ||
60 | |||
61 | #define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6 | ||
62 | #define S5P_FIMV_R2H_CMD_SLEEP_RET_V6 7 | ||
63 | #define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6 8 | ||
64 | #define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6 9 | ||
65 | #define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6 10 | ||
66 | #define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6 11 | ||
67 | #define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6 12 | ||
68 | #define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6 13 | ||
69 | #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6 14 | ||
70 | #define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6 15 | ||
71 | #define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16 | ||
72 | #define S5P_FIMV_R2H_CMD_ERR_RET_V6 32 | ||
73 | |||
74 | #define S5P_FIMV_FW_VERSION_V6 0xf000 | ||
75 | |||
76 | #define S5P_FIMV_INSTANCE_ID_V6 0xf008 | ||
77 | #define S5P_FIMV_CODEC_TYPE_V6 0xf00c | ||
78 | #define S5P_FIMV_CONTEXT_MEM_ADDR_V6 0xf014 | ||
79 | #define S5P_FIMV_CONTEXT_MEM_SIZE_V6 0xf018 | ||
80 | #define S5P_FIMV_PIXEL_FORMAT_V6 0xf020 | ||
81 | |||
82 | #define S5P_FIMV_METADATA_ENABLE_V6 0xf024 | ||
83 | #define S5P_FIMV_DBG_BUFFER_ADDR_V6 0xf030 | ||
84 | #define S5P_FIMV_DBG_BUFFER_SIZE_V6 0xf034 | ||
85 | #define S5P_FIMV_RET_INSTANCE_ID_V6 0xf070 | ||
86 | |||
87 | #define S5P_FIMV_ERROR_CODE_V6 0xf074 | ||
88 | #define S5P_FIMV_ERR_WARNINGS_START_V6 160 | ||
89 | #define S5P_FIMV_ERR_DEC_MASK_V6 0xffff | ||
90 | #define S5P_FIMV_ERR_DEC_SHIFT_V6 0 | ||
91 | #define S5P_FIMV_ERR_DSPL_MASK_V6 0xffff0000 | ||
92 | #define S5P_FIMV_ERR_DSPL_SHIFT_V6 16 | ||
93 | |||
94 | #define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6 0xf078 | ||
95 | #define S5P_FIMV_METADATA_STATUS_V6 0xf07C | ||
96 | #define S5P_FIMV_METADATA_ADDR_MB_INFO_V6 0xf080 | ||
97 | #define S5P_FIMV_METADATA_SIZE_MB_INFO_V6 0xf084 | ||
98 | |||
99 | /* Decoder Registers */ | ||
100 | #define S5P_FIMV_D_CRC_CTRL_V6 0xf0b0 | ||
101 | #define S5P_FIMV_D_DEC_OPTIONS_V6 0xf0b4 | ||
102 | #define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6 4 | ||
103 | #define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6 3 | ||
104 | #define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6 1 | ||
105 | #define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6 0x3 | ||
106 | #define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6 0 | ||
107 | |||
108 | #define S5P_FIMV_D_DISPLAY_DELAY_V6 0xf0b8 | ||
109 | |||
110 | #define S5P_FIMV_D_SET_FRAME_WIDTH_V6 0xf0bc | ||
111 | #define S5P_FIMV_D_SET_FRAME_HEIGHT_V6 0xf0c0 | ||
112 | |||
113 | #define S5P_FIMV_D_SEI_ENABLE_V6 0xf0c4 | ||
114 | |||
115 | /* Buffer setting registers */ | ||
116 | #define S5P_FIMV_D_MIN_NUM_DPB_V6 0xf0f0 | ||
117 | #define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6 0xf0f4 | ||
118 | #define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6 0xf0f8 | ||
119 | #define S5P_FIMV_D_MVC_NUM_VIEWS_V6 0xf0fc | ||
120 | #define S5P_FIMV_D_MIN_NUM_MV_V6 0xf100 | ||
121 | #define S5P_FIMV_D_NUM_DPB_V6 0xf130 | ||
122 | #define S5P_FIMV_D_LUMA_DPB_SIZE_V6 0xf134 | ||
123 | #define S5P_FIMV_D_CHROMA_DPB_SIZE_V6 0xf138 | ||
124 | #define S5P_FIMV_D_MV_BUFFER_SIZE_V6 0xf13c | ||
125 | |||
126 | #define S5P_FIMV_D_LUMA_DPB_V6 0xf140 | ||
127 | #define S5P_FIMV_D_CHROMA_DPB_V6 0xf240 | ||
128 | #define S5P_FIMV_D_MV_BUFFER_V6 0xf340 | ||
129 | |||
130 | #define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6 0xf440 | ||
131 | #define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6 0xf444 | ||
132 | #define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6 0xf448 | ||
133 | #define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6 0xf44c | ||
134 | #define S5P_FIMV_D_NUM_MV_V6 0xf478 | ||
135 | #define S5P_FIMV_D_CPB_BUFFER_ADDR_V6 0xf4b0 | ||
136 | #define S5P_FIMV_D_CPB_BUFFER_SIZE_V6 0xf4b4 | ||
137 | |||
138 | #define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8 | ||
139 | #define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc | ||
140 | #define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6 0xf4c0 | ||
141 | #define S5P_FIMV_D_SLICE_IF_ENABLE_V6 0xf4c4 | ||
142 | #define S5P_FIMV_D_PICTURE_TAG_V6 0xf4c8 | ||
143 | #define S5P_FIMV_D_STREAM_DATA_SIZE_V6 0xf4d0 | ||
144 | |||
145 | /* Display information register */ | ||
146 | #define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6 0xf500 | ||
147 | #define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6 0xf504 | ||
148 | |||
149 | /* Display status */ | ||
150 | #define S5P_FIMV_D_DISPLAY_STATUS_V6 0xf508 | ||
151 | |||
152 | #define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6 0xf50c | ||
153 | #define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6 0xf510 | ||
154 | |||
155 | #define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6 0xf514 | ||
156 | |||
157 | #define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 0xf518 | ||
158 | #define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 0xf51c | ||
159 | #define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6 0xf520 | ||
160 | #define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6 0xf524 | ||
161 | #define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6 0xf528 | ||
162 | #define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6 0xf52c | ||
163 | #define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6 0xf530 | ||
164 | #define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6 0xf534 | ||
165 | #define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6 0xf538 | ||
166 | |||
167 | /* Decoded picture information register */ | ||
168 | #define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6 0xf53c | ||
169 | #define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6 0xf540 | ||
170 | #define S5P_FIMV_D_DECODED_STATUS_V6 0xf544 | ||
171 | #define S5P_FIMV_DEC_CRC_GEN_MASK_V6 0x1 | ||
172 | #define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6 6 | ||
173 | |||
174 | #define S5P_FIMV_D_DECODED_LUMA_ADDR_V6 0xf548 | ||
175 | #define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6 0xf54c | ||
176 | |||
177 | #define S5P_FIMV_D_DECODED_FRAME_TYPE_V6 0xf550 | ||
178 | #define S5P_FIMV_DECODE_FRAME_MASK_V6 7 | ||
179 | |||
180 | #define S5P_FIMV_D_DECODED_CROP_INFO1_V6 0xf554 | ||
181 | #define S5P_FIMV_D_DECODED_CROP_INFO2_V6 0xf558 | ||
182 | #define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6 0xf55c | ||
183 | #define S5P_FIMV_D_DECODED_NAL_SIZE_V6 0xf560 | ||
184 | #define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6 0xf564 | ||
185 | #define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6 0xf568 | ||
186 | #define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6 0xf56c | ||
187 | #define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6 0xf570 | ||
188 | |||
189 | /* Returned value register for specific setting */ | ||
190 | #define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 0xf574 | ||
191 | #define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 0xf578 | ||
192 | #define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6 0xf57c | ||
193 | #define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6 0xf580 | ||
194 | #define S5P_FIMV_D_CHROMA_FORMAT_V6 0xf588 | ||
195 | #define S5P_FIMV_D_MPEG4_INFO_V6 0xf58c | ||
196 | #define S5P_FIMV_D_H264_INFO_V6 0xf590 | ||
197 | |||
198 | #define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6 0xf594 | ||
199 | #define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6 0xf598 | ||
200 | #define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6 0xf59c | ||
201 | #define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6 0xf5a0 | ||
202 | #define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6 0xf5a4 | ||
203 | #define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6 0xf5a8 | ||
204 | #define S5P_FIMV_D_METADATA_ADDR_VUI_V6 0xf5ac | ||
205 | #define S5P_FIMV_D_METADATA_SIZE_VUI_V6 0xf5b0 | ||
206 | |||
207 | #define S5P_FIMV_D_MVC_VIEW_ID_V6 0xf5b4 | ||
208 | |||
209 | /* SEI related information */ | ||
210 | #define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6 0xf5f0 | ||
211 | #define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6 0xf5f4 | ||
212 | #define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6 0xf5f8 | ||
213 | #define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6 0xf5fc | ||
214 | |||
215 | /* Encoder Registers */ | ||
216 | #define S5P_FIMV_E_FRAME_WIDTH_V6 0xf770 | ||
217 | #define S5P_FIMV_E_FRAME_HEIGHT_V6 0xf774 | ||
218 | #define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6 0xf778 | ||
219 | #define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6 0xf77c | ||
220 | #define S5P_FIMV_E_FRAME_CROP_OFFSET_V6 0xf780 | ||
221 | #define S5P_FIMV_E_ENC_OPTIONS_V6 0xf784 | ||
222 | #define S5P_FIMV_E_PICTURE_PROFILE_V6 0xf788 | ||
223 | #define S5P_FIMV_E_FIXED_PICTURE_QP_V6 0xf790 | ||
224 | |||
225 | #define S5P_FIMV_E_RC_CONFIG_V6 0xf794 | ||
226 | #define S5P_FIMV_E_RC_QP_BOUND_V6 0xf798 | ||
227 | #define S5P_FIMV_E_RC_RPARAM_V6 0xf79c | ||
228 | #define S5P_FIMV_E_MB_RC_CONFIG_V6 0xf7a0 | ||
229 | #define S5P_FIMV_E_PADDING_CTRL_V6 0xf7a4 | ||
230 | #define S5P_FIMV_E_MV_HOR_RANGE_V6 0xf7ac | ||
231 | #define S5P_FIMV_E_MV_VER_RANGE_V6 0xf7b0 | ||
232 | |||
233 | #define S5P_FIMV_E_VBV_BUFFER_SIZE_V6 0xf84c | ||
234 | #define S5P_FIMV_E_VBV_INIT_DELAY_V6 0xf850 | ||
235 | #define S5P_FIMV_E_NUM_DPB_V6 0xf890 | ||
236 | #define S5P_FIMV_E_LUMA_DPB_V6 0xf8c0 | ||
237 | #define S5P_FIMV_E_CHROMA_DPB_V6 0xf904 | ||
238 | #define S5P_FIMV_E_ME_BUFFER_V6 0xf948 | ||
239 | |||
240 | #define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6 0xf98c | ||
241 | #define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6 0xf990 | ||
242 | #define S5P_FIMV_E_TMV_BUFFER0_V6 0xf994 | ||
243 | #define S5P_FIMV_E_TMV_BUFFER1_V6 0xf998 | ||
244 | #define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6 0xf9f0 | ||
245 | #define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6 0xf9f4 | ||
246 | #define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6 0xf9f8 | ||
247 | #define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6 0xf9fc | ||
248 | #define S5P_FIMV_E_ROI_BUFFER_ADDR_V6 0xfA00 | ||
249 | |||
250 | #define S5P_FIMV_E_PARAM_CHANGE_V6 0xfa04 | ||
251 | #define S5P_FIMV_E_IR_SIZE_V6 0xfa08 | ||
252 | #define S5P_FIMV_E_GOP_CONFIG_V6 0xfa0c | ||
253 | #define S5P_FIMV_E_MSLICE_MODE_V6 0xfa10 | ||
254 | #define S5P_FIMV_E_MSLICE_SIZE_MB_V6 0xfa14 | ||
255 | #define S5P_FIMV_E_MSLICE_SIZE_BITS_V6 0xfa18 | ||
256 | #define S5P_FIMV_E_FRAME_INSERTION_V6 0xfa1c | ||
257 | |||
258 | #define S5P_FIMV_E_RC_FRAME_RATE_V6 0xfa20 | ||
259 | #define S5P_FIMV_E_RC_BIT_RATE_V6 0xfa24 | ||
260 | #define S5P_FIMV_E_RC_QP_OFFSET_V6 0xfa28 | ||
261 | #define S5P_FIMV_E_RC_ROI_CTRL_V6 0xfa2c | ||
262 | #define S5P_FIMV_E_PICTURE_TAG_V6 0xfa30 | ||
263 | #define S5P_FIMV_E_BIT_COUNT_ENABLE_V6 0xfa34 | ||
264 | #define S5P_FIMV_E_MAX_BIT_COUNT_V6 0xfa38 | ||
265 | #define S5P_FIMV_E_MIN_BIT_COUNT_V6 0xfa3c | ||
266 | |||
267 | #define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6 0xfa40 | ||
268 | #define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6 0xfa44 | ||
269 | #define S5P_FIMV_E_STREAM_SIZE_V6 0xfa80 | ||
270 | #define S5P_FIMV_E_SLICE_TYPE_V6 0xfa84 | ||
271 | #define S5P_FIMV_E_PICTURE_COUNT_V6 0xfa88 | ||
272 | #define S5P_FIMV_E_RET_PICTURE_TAG_V6 0xfa8c | ||
273 | #define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6 0xfa90 | ||
274 | |||
275 | #define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6 0xfa94 | ||
276 | #define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6 0xfa98 | ||
277 | #define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6 0xfa9c | ||
278 | #define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6 0xfaa0 | ||
279 | #define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6 0xfaa4 | ||
280 | #define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6 0xfaa8 | ||
281 | |||
282 | #define S5P_FIMV_E_MPEG4_OPTIONS_V6 0xfb10 | ||
283 | #define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6 0xfb14 | ||
284 | #define S5P_FIMV_E_ASPECT_RATIO_V6 0xfb50 | ||
285 | #define S5P_FIMV_E_EXTENDED_SAR_V6 0xfb54 | ||
286 | |||
287 | #define S5P_FIMV_E_H264_OPTIONS_V6 0xfb58 | ||
288 | #define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6 0xfb5c | ||
289 | #define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6 0xfb60 | ||
290 | #define S5P_FIMV_E_H264_I_PERIOD_V6 0xfb64 | ||
291 | |||
292 | #define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6 0xfb68 | ||
293 | #define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6 0xfb6c | ||
294 | #define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6 0xfb70 | ||
295 | #define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6 0xfb74 | ||
296 | #define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 0xfb78 | ||
297 | #define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6 0xfb7c | ||
298 | #define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6 0xfb80 | ||
299 | #define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6 0xfb84 | ||
300 | |||
301 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 0xfb88 | ||
302 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6 0xfb8c | ||
303 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6 0xfb90 | ||
304 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6 0xfb94 | ||
305 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6 0xfb98 | ||
306 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6 0xfb9c | ||
307 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6 0xfba0 | ||
308 | #define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6 0xfba4 | ||
309 | |||
310 | #define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6 0xfba8 | ||
311 | #define S5P_FIMV_E_H264_NUM_T_LAYER_V6 0xfbac | ||
312 | |||
313 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 0xfbb0 | ||
314 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6 0xfbb4 | ||
315 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6 0xfbb8 | ||
316 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6 0xfbbc | ||
317 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6 0xfbc0 | ||
318 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6 0xfbc4 | ||
319 | #define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6 0xfbc8 | ||
320 | |||
321 | #define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6 0xfc4c | ||
322 | #define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6 0 | ||
323 | #define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6 1 | ||
324 | #define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6 2 | ||
325 | |||
326 | #define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6 0xfd40 | ||
327 | #define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6 0xfd44 | ||
328 | #define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6 0xfd48 | ||
329 | #define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6 0xfd4c | ||
330 | #define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6 0xfd50 | ||
331 | #define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6 0xfd80 | ||
332 | |||
333 | /* Codec numbers */ | ||
334 | #define S5P_FIMV_CODEC_NONE_V6 -1 | ||
335 | |||
336 | |||
337 | #define S5P_FIMV_CODEC_H264_DEC_V6 0 | ||
338 | #define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1 | ||
339 | |||
340 | #define S5P_FIMV_CODEC_MPEG4_DEC_V6 3 | ||
341 | #define S5P_FIMV_CODEC_FIMV1_DEC_V6 4 | ||
342 | #define S5P_FIMV_CODEC_FIMV2_DEC_V6 5 | ||
343 | #define S5P_FIMV_CODEC_FIMV3_DEC_V6 6 | ||
344 | #define S5P_FIMV_CODEC_FIMV4_DEC_V6 7 | ||
345 | #define S5P_FIMV_CODEC_H263_DEC_V6 8 | ||
346 | #define S5P_FIMV_CODEC_VC1RCV_DEC_V6 9 | ||
347 | #define S5P_FIMV_CODEC_VC1_DEC_V6 10 | ||
348 | /* FIXME: Add 11~12 */ | ||
349 | #define S5P_FIMV_CODEC_MPEG2_DEC_V6 13 | ||
350 | #define S5P_FIMV_CODEC_VP8_DEC_V6 14 | ||
351 | /* FIXME: Add 15~16 */ | ||
352 | #define S5P_FIMV_CODEC_H264_ENC_V6 20 | ||
353 | #define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21 | ||
354 | |||
355 | #define S5P_FIMV_CODEC_MPEG4_ENC_V6 23 | ||
356 | #define S5P_FIMV_CODEC_H263_ENC_V6 24 | ||
357 | |||
358 | #define S5P_FIMV_NV12M_HALIGN_V6 16 | ||
359 | #define S5P_FIMV_NV12MT_HALIGN_V6 16 | ||
360 | #define S5P_FIMV_NV12MT_VALIGN_V6 16 | ||
361 | |||
362 | #define S5P_FIMV_TMV_BUFFER_ALIGN_V6 16 | ||
363 | #define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6 256 | ||
364 | #define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6 256 | ||
365 | #define S5P_FIMV_ME_BUFFER_ALIGN_V6 256 | ||
366 | #define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6 256 | ||
367 | |||
368 | #define S5P_FIMV_LUMA_MB_TO_PIXEL_V6 256 | ||
369 | #define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6 128 | ||
370 | #define S5P_FIMV_NUM_TMV_BUFFERS_V6 2 | ||
371 | |||
372 | #define S5P_FIMV_MAX_FRAME_SIZE_V6 (2 * SZ_1M) | ||
373 | #define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6 16 | ||
374 | #define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16 | ||
375 | |||
376 | /* Buffer size requirements defined by hardware */ | ||
377 | #define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8) | ||
378 | #define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \ | ||
379 | ((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \ | ||
380 | (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) | ||
381 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) | ||
382 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ | ||
383 | ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \ | ||
384 | (2048/16 * 256 + 8320)) | ||
385 | #define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \ | ||
386 | (2096 * ((w) + (h) + 1)) | ||
387 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h) ((w) * 400) | ||
388 | #define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \ | ||
389 | ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112) | ||
390 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \ | ||
391 | (((w) * 64) + (((w) + 1) * 16) + (4096 * 16)) | ||
392 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \ | ||
393 | (((w) * 16) + (((w) + 1) * 16)) | ||
394 | |||
395 | /* MFC Context buffer sizes */ | ||
396 | #define MFC_CTX_BUF_SIZE_V6 (28 * SZ_1K) /* 28KB */ | ||
397 | #define MFC_H264_DEC_CTX_BUF_SIZE_V6 (2 * SZ_1M) /* 2MB */ | ||
398 | #define MFC_OTHER_DEC_CTX_BUF_SIZE_V6 (20 * SZ_1K) /* 20KB */ | ||
399 | #define MFC_H264_ENC_CTX_BUF_SIZE_V6 (100 * SZ_1K) /* 100KB */ | ||
400 | #define MFC_OTHER_ENC_CTX_BUF_SIZE_V6 (12 * SZ_1K) /* 12KB */ | ||
401 | |||
402 | /* MFCv6 variant defines */ | ||
403 | #define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */ | ||
404 | #define MAX_CPB_SIZE_V6 (3 * SZ_1M) /* 3MB */ | ||
405 | #define MFC_VERSION_V6 0x61 | ||
406 | #define MFC_NUM_PORTS_V6 1 | ||
407 | |||
408 | #endif /* _REGS_FIMV_V6_H */ | ||
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h index a19bece41ba9..9319e93599ae 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h | |||
@@ -12,6 +12,9 @@ | |||
12 | #ifndef _REGS_FIMV_H | 12 | #ifndef _REGS_FIMV_H |
13 | #define _REGS_FIMV_H | 13 | #define _REGS_FIMV_H |
14 | 14 | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/sizes.h> | ||
17 | |||
15 | #define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) | 18 | #define S5P_FIMV_REG_SIZE (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) |
16 | #define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4) | 19 | #define S5P_FIMV_REG_COUNT ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4) |
17 | 20 | ||
@@ -144,6 +147,7 @@ | |||
144 | #define S5P_FIMV_ENC_PROFILE_H264_MAIN 0 | 147 | #define S5P_FIMV_ENC_PROFILE_H264_MAIN 0 |
145 | #define S5P_FIMV_ENC_PROFILE_H264_HIGH 1 | 148 | #define S5P_FIMV_ENC_PROFILE_H264_HIGH 1 |
146 | #define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2 | 149 | #define S5P_FIMV_ENC_PROFILE_H264_BASELINE 2 |
150 | #define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3 | ||
147 | #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0 | 151 | #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE 0 |
148 | #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1 | 152 | #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE 1 |
149 | #define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */ | 153 | #define S5P_FIMV_ENC_PIC_STRUCT 0x083c /* picture field/frame flag */ |
@@ -213,6 +217,7 @@ | |||
213 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4) | 217 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK (3<<4) |
214 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4) | 218 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC (1<<4) |
215 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4) | 219 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC (2<<4) |
220 | #define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT 4 | ||
216 | 221 | ||
217 | /* Decode frame address */ | 222 | /* Decode frame address */ |
218 | #define S5P_FIMV_DECODE_Y_ADR 0x2024 | 223 | #define S5P_FIMV_DECODE_Y_ADR 0x2024 |
@@ -377,6 +382,16 @@ | |||
377 | #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16 | 382 | #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16 |
378 | #define S5P_FIMV_R2H_CMD_ERR_RET 32 | 383 | #define S5P_FIMV_R2H_CMD_ERR_RET 32 |
379 | 384 | ||
385 | /* Dummy definition for MFCv6 compatibilty */ | ||
386 | #define S5P_FIMV_CODEC_H264_MVC_DEC -1 | ||
387 | #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1 | ||
388 | #define S5P_FIMV_MFC_RESET -1 | ||
389 | #define S5P_FIMV_RISC_ON -1 | ||
390 | #define S5P_FIMV_RISC_BASE_ADDRESS -1 | ||
391 | #define S5P_FIMV_CODEC_VP8_DEC -1 | ||
392 | #define S5P_FIMV_REG_CLEAR_BEGIN 0 | ||
393 | #define S5P_FIMV_REG_CLEAR_COUNT 0 | ||
394 | |||
380 | /* Error handling defines */ | 395 | /* Error handling defines */ |
381 | #define S5P_FIMV_ERR_WARNINGS_START 145 | 396 | #define S5P_FIMV_ERR_WARNINGS_START 145 |
382 | #define S5P_FIMV_ERR_DEC_MASK 0xFFFF | 397 | #define S5P_FIMV_ERR_DEC_MASK 0xFFFF |
@@ -414,5 +429,31 @@ | |||
414 | #define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078 | 429 | #define S5P_FIMV_SHARED_EXTENDED_SAR 0x0078 |
415 | #define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C | 430 | #define S5P_FIMV_SHARED_H264_I_PERIOD 0x009C |
416 | #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0 | 431 | #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG 0x00A0 |
432 | #define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT 2 | ||
433 | |||
434 | /* Offset used by the hardware to store addresses */ | ||
435 | #define MFC_OFFSET_SHIFT 11 | ||
436 | |||
437 | #define FIRMWARE_ALIGN (128 * SZ_1K) /* 128KB */ | ||
438 | #define MFC_H264_CTX_BUF_SIZE (600 * SZ_1K) /* 600KB per H264 instance */ | ||
439 | #define MFC_CTX_BUF_SIZE (10 * SZ_1K) /* 10KB per instance */ | ||
440 | #define DESC_BUF_SIZE (128 * SZ_1K) /* 128KB for DESC buffer */ | ||
441 | #define SHARED_BUF_SIZE (8 * SZ_1K) /* 8KB for shared buffer */ | ||
442 | |||
443 | #define DEF_CPB_SIZE (256 * SZ_1K) /* 256KB */ | ||
444 | #define MAX_CPB_SIZE (4 * SZ_1M) /* 4MB */ | ||
445 | #define MAX_FW_SIZE (384 * SZ_1K) | ||
446 | |||
447 | #define MFC_VERSION 0x51 | ||
448 | #define MFC_NUM_PORTS 2 | ||
449 | |||
450 | #define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL 0x16C | ||
451 | #define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID 0x170 | ||
452 | #define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO 0x174 | ||
453 | #define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS 0x178 | ||
454 | |||
455 | /* Values for resolution change in display status */ | ||
456 | #define S5P_FIMV_RES_INCREASE 1 | ||
457 | #define S5P_FIMV_RES_DECREASE 2 | ||
417 | 458 | ||
418 | #endif /* _REGS_FIMV_H */ | 459 | #endif /* _REGS_FIMV_H */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 5587ef15ca4f..130f4ac8649e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -22,15 +22,15 @@ | |||
22 | #include <media/v4l2-event.h> | 22 | #include <media/v4l2-event.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <media/videobuf2-core.h> | 24 | #include <media/videobuf2-core.h> |
25 | #include "regs-mfc.h" | 25 | #include "s5p_mfc_common.h" |
26 | #include "s5p_mfc_ctrl.h" | 26 | #include "s5p_mfc_ctrl.h" |
27 | #include "s5p_mfc_debug.h" | 27 | #include "s5p_mfc_debug.h" |
28 | #include "s5p_mfc_dec.h" | 28 | #include "s5p_mfc_dec.h" |
29 | #include "s5p_mfc_enc.h" | 29 | #include "s5p_mfc_enc.h" |
30 | #include "s5p_mfc_intr.h" | 30 | #include "s5p_mfc_intr.h" |
31 | #include "s5p_mfc_opr.h" | 31 | #include "s5p_mfc_opr.h" |
32 | #include "s5p_mfc_cmd.h" | ||
32 | #include "s5p_mfc_pm.h" | 33 | #include "s5p_mfc_pm.h" |
33 | #include "s5p_mfc_shm.h" | ||
34 | 34 | ||
35 | #define S5P_MFC_NAME "s5p-mfc" | 35 | #define S5P_MFC_NAME "s5p-mfc" |
36 | #define S5P_MFC_DEC_NAME "s5p-mfc-dec" | 36 | #define S5P_MFC_DEC_NAME "s5p-mfc-dec" |
@@ -149,10 +149,12 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work) | |||
149 | if (!ctx) | 149 | if (!ctx) |
150 | continue; | 150 | continue; |
151 | ctx->state = MFCINST_ERROR; | 151 | ctx->state = MFCINST_ERROR; |
152 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); | 152 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, |
153 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); | 153 | &ctx->vq_dst); |
154 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, | ||
155 | &ctx->vq_src); | ||
154 | clear_work_bit(ctx); | 156 | clear_work_bit(ctx); |
155 | wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0); | 157 | wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0); |
156 | } | 158 | } |
157 | clear_bit(0, &dev->hw_lock); | 159 | clear_bit(0, &dev->hw_lock); |
158 | spin_unlock_irqrestore(&dev->irqlock, flags); | 160 | spin_unlock_irqrestore(&dev->irqlock, flags); |
@@ -199,6 +201,7 @@ static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev) | |||
199 | static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) | 201 | static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) |
200 | { | 202 | { |
201 | struct s5p_mfc_buf *dst_buf; | 203 | struct s5p_mfc_buf *dst_buf; |
204 | struct s5p_mfc_dev *dev = ctx->dev; | ||
202 | 205 | ||
203 | ctx->state = MFCINST_FINISHED; | 206 | ctx->state = MFCINST_FINISHED; |
204 | ctx->sequence++; | 207 | ctx->sequence++; |
@@ -213,8 +216,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) | |||
213 | ctx->dst_queue_cnt--; | 216 | ctx->dst_queue_cnt--; |
214 | dst_buf->b->v4l2_buf.sequence = (ctx->sequence++); | 217 | dst_buf->b->v4l2_buf.sequence = (ctx->sequence++); |
215 | 218 | ||
216 | if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) == | 219 | if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) == |
217 | s5p_mfc_read_shm(ctx, PIC_TIME_BOT)) | 220 | s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx)) |
218 | dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE; | 221 | dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE; |
219 | else | 222 | else |
220 | dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED; | 223 | 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) | |||
228 | { | 231 | { |
229 | struct s5p_mfc_dev *dev = ctx->dev; | 232 | struct s5p_mfc_dev *dev = ctx->dev; |
230 | struct s5p_mfc_buf *dst_buf, *src_buf; | 233 | struct s5p_mfc_buf *dst_buf, *src_buf; |
231 | size_t dec_y_addr = s5p_mfc_get_dec_y_adr(); | 234 | size_t dec_y_addr; |
232 | unsigned int frame_type = s5p_mfc_get_frame_type(); | 235 | unsigned int frame_type; |
236 | |||
237 | dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev); | ||
238 | frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); | ||
233 | 239 | ||
234 | /* Copy timestamp / timecode from decoded src to dst and set | 240 | /* Copy timestamp / timecode from decoded src to dst and set |
235 | appropraite flags */ | 241 | appropraite flags */ |
@@ -265,10 +271,13 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) | |||
265 | { | 271 | { |
266 | struct s5p_mfc_dev *dev = ctx->dev; | 272 | struct s5p_mfc_dev *dev = ctx->dev; |
267 | struct s5p_mfc_buf *dst_buf; | 273 | struct s5p_mfc_buf *dst_buf; |
268 | size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr(); | 274 | size_t dspl_y_addr; |
269 | unsigned int frame_type = s5p_mfc_get_frame_type(); | 275 | unsigned int frame_type; |
270 | unsigned int index; | 276 | unsigned int index; |
271 | 277 | ||
278 | dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); | ||
279 | frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); | ||
280 | |||
272 | /* If frame is same as previous then skip and do not dequeue */ | 281 | /* If frame is same as previous then skip and do not dequeue */ |
273 | if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) { | 282 | if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) { |
274 | if (!ctx->after_packed_pb) | 283 | if (!ctx->after_packed_pb) |
@@ -285,8 +294,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) | |||
285 | list_del(&dst_buf->list); | 294 | list_del(&dst_buf->list); |
286 | ctx->dst_queue_cnt--; | 295 | ctx->dst_queue_cnt--; |
287 | dst_buf->b->v4l2_buf.sequence = ctx->sequence; | 296 | dst_buf->b->v4l2_buf.sequence = ctx->sequence; |
288 | if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) == | 297 | if (s5p_mfc_hw_call(dev->mfc_ops, |
289 | s5p_mfc_read_shm(ctx, PIC_TIME_BOT)) | 298 | get_pic_type_top, ctx) == |
299 | s5p_mfc_hw_call(dev->mfc_ops, | ||
300 | get_pic_type_bot, ctx)) | ||
290 | dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE; | 301 | dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE; |
291 | else | 302 | else |
292 | dst_buf->b->v4l2_buf.field = | 303 | dst_buf->b->v4l2_buf.field = |
@@ -317,21 +328,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, | |||
317 | 328 | ||
318 | unsigned int index; | 329 | unsigned int index; |
319 | 330 | ||
320 | dst_frame_status = s5p_mfc_get_dspl_status() | 331 | dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) |
321 | & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; | 332 | & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; |
322 | res_change = s5p_mfc_get_dspl_status() | 333 | res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) |
323 | & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK; | 334 | & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK) |
335 | >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT; | ||
324 | mfc_debug(2, "Frame Status: %x\n", dst_frame_status); | 336 | mfc_debug(2, "Frame Status: %x\n", dst_frame_status); |
325 | if (ctx->state == MFCINST_RES_CHANGE_INIT) | 337 | if (ctx->state == MFCINST_RES_CHANGE_INIT) |
326 | ctx->state = MFCINST_RES_CHANGE_FLUSH; | 338 | ctx->state = MFCINST_RES_CHANGE_FLUSH; |
327 | if (res_change) { | 339 | if (res_change == S5P_FIMV_RES_INCREASE || |
340 | res_change == S5P_FIMV_RES_DECREASE) { | ||
328 | ctx->state = MFCINST_RES_CHANGE_INIT; | 341 | ctx->state = MFCINST_RES_CHANGE_INIT; |
329 | s5p_mfc_clear_int_flags(dev); | 342 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
330 | wake_up_ctx(ctx, reason, err); | 343 | wake_up_ctx(ctx, reason, err); |
331 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 344 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) |
332 | BUG(); | 345 | BUG(); |
333 | s5p_mfc_clock_off(); | 346 | s5p_mfc_clock_off(); |
334 | s5p_mfc_try_run(dev); | 347 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
335 | return; | 348 | return; |
336 | } | 349 | } |
337 | if (ctx->dpb_flush_flag) | 350 | if (ctx->dpb_flush_flag) |
@@ -365,9 +378,12 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, | |||
365 | && !list_empty(&ctx->src_queue)) { | 378 | && !list_empty(&ctx->src_queue)) { |
366 | src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, | 379 | src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, |
367 | list); | 380 | list); |
368 | ctx->consumed_stream += s5p_mfc_get_consumed_stream(); | 381 | ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops, |
369 | if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC && | 382 | get_consumed_stream, dev); |
370 | s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME | 383 | if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC && |
384 | s5p_mfc_hw_call(dev->mfc_ops, | ||
385 | get_dec_frame_type, dev) == | ||
386 | S5P_FIMV_DECODE_FRAME_P_FRAME | ||
371 | && ctx->consumed_stream + STUFF_BYTE < | 387 | && ctx->consumed_stream + STUFF_BYTE < |
372 | src_buf->b->v4l2_planes[0].bytesused) { | 388 | src_buf->b->v4l2_planes[0].bytesused) { |
373 | /* Run MFC again on the same buffer */ | 389 | /* Run MFC again on the same buffer */ |
@@ -379,7 +395,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, | |||
379 | ctx->consumed_stream = 0; | 395 | ctx->consumed_stream = 0; |
380 | list_del(&src_buf->list); | 396 | list_del(&src_buf->list); |
381 | ctx->src_queue_cnt--; | 397 | ctx->src_queue_cnt--; |
382 | if (s5p_mfc_err_dec(err) > 0) | 398 | if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0) |
383 | vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR); | 399 | vb2_buffer_done(src_buf->b, VB2_BUF_STATE_ERROR); |
384 | else | 400 | else |
385 | vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE); | 401 | vb2_buffer_done(src_buf->b, VB2_BUF_STATE_DONE); |
@@ -390,12 +406,12 @@ leave_handle_frame: | |||
390 | if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) | 406 | if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) |
391 | || ctx->dst_queue_cnt < ctx->dpb_count) | 407 | || ctx->dst_queue_cnt < ctx->dpb_count) |
392 | clear_work_bit(ctx); | 408 | clear_work_bit(ctx); |
393 | s5p_mfc_clear_int_flags(dev); | 409 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
394 | wake_up_ctx(ctx, reason, err); | 410 | wake_up_ctx(ctx, reason, err); |
395 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 411 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) |
396 | BUG(); | 412 | BUG(); |
397 | s5p_mfc_clock_off(); | 413 | s5p_mfc_clock_off(); |
398 | s5p_mfc_try_run(dev); | 414 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
399 | } | 415 | } |
400 | 416 | ||
401 | /* Error handling for interrupt */ | 417 | /* Error handling for interrupt */ |
@@ -412,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, | |||
412 | 428 | ||
413 | dev = ctx->dev; | 429 | dev = ctx->dev; |
414 | mfc_err("Interrupt Error: %08x\n", err); | 430 | mfc_err("Interrupt Error: %08x\n", err); |
415 | s5p_mfc_clear_int_flags(dev); | 431 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
416 | wake_up_dev(dev, reason, err); | 432 | wake_up_dev(dev, reason, err); |
417 | 433 | ||
418 | /* Error recovery is dependent on the state of context */ | 434 | /* Error recovery is dependent on the state of context */ |
@@ -441,9 +457,11 @@ static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, | |||
441 | ctx->state = MFCINST_ERROR; | 457 | ctx->state = MFCINST_ERROR; |
442 | /* Mark all dst buffers as having an error */ | 458 | /* Mark all dst buffers as having an error */ |
443 | spin_lock_irqsave(&dev->irqlock, flags); | 459 | spin_lock_irqsave(&dev->irqlock, flags); |
444 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); | 460 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, |
461 | &ctx->vq_dst); | ||
445 | /* Mark all src buffers as having an error */ | 462 | /* Mark all src buffers as having an error */ |
446 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); | 463 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, |
464 | &ctx->vq_src); | ||
447 | spin_unlock_irqrestore(&dev->irqlock, flags); | 465 | spin_unlock_irqrestore(&dev->irqlock, flags); |
448 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 466 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) |
449 | BUG(); | 467 | BUG(); |
@@ -461,7 +479,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, | |||
461 | unsigned int reason, unsigned int err) | 479 | unsigned int reason, unsigned int err) |
462 | { | 480 | { |
463 | struct s5p_mfc_dev *dev; | 481 | struct s5p_mfc_dev *dev; |
464 | unsigned int guard_width, guard_height; | ||
465 | 482 | ||
466 | if (ctx == NULL) | 483 | if (ctx == NULL) |
467 | return; | 484 | return; |
@@ -470,55 +487,44 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, | |||
470 | if (ctx->c_ops->post_seq_start(ctx)) | 487 | if (ctx->c_ops->post_seq_start(ctx)) |
471 | mfc_err("post_seq_start() failed\n"); | 488 | mfc_err("post_seq_start() failed\n"); |
472 | } else { | 489 | } else { |
473 | ctx->img_width = s5p_mfc_get_img_width(); | 490 | ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width, |
474 | ctx->img_height = s5p_mfc_get_img_height(); | 491 | dev); |
475 | 492 | ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height, | |
476 | ctx->buf_width = ALIGN(ctx->img_width, | 493 | dev); |
477 | S5P_FIMV_NV12MT_HALIGN); | 494 | |
478 | ctx->buf_height = ALIGN(ctx->img_height, | 495 | s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx); |
479 | S5P_FIMV_NV12MT_VALIGN); | 496 | |
480 | mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, " | 497 | ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, |
481 | "buffer dimensions: %dx%d\n", ctx->img_width, | 498 | dev); |
482 | ctx->img_height, ctx->buf_width, | 499 | ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count, |
483 | ctx->buf_height); | 500 | dev); |
484 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) { | ||
485 | ctx->luma_size = ALIGN(ctx->buf_width * | ||
486 | ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN); | ||
487 | ctx->chroma_size = ALIGN(ctx->buf_width * | ||
488 | ALIGN((ctx->img_height >> 1), | ||
489 | S5P_FIMV_NV12MT_VALIGN), | ||
490 | S5P_FIMV_DEC_BUF_ALIGN); | ||
491 | ctx->mv_size = ALIGN(ctx->buf_width * | ||
492 | ALIGN((ctx->buf_height >> 2), | ||
493 | S5P_FIMV_NV12MT_VALIGN), | ||
494 | S5P_FIMV_DEC_BUF_ALIGN); | ||
495 | } else { | ||
496 | guard_width = ALIGN(ctx->img_width + 24, | ||
497 | S5P_FIMV_NV12MT_HALIGN); | ||
498 | guard_height = ALIGN(ctx->img_height + 16, | ||
499 | S5P_FIMV_NV12MT_VALIGN); | ||
500 | ctx->luma_size = ALIGN(guard_width * | ||
501 | guard_height, S5P_FIMV_DEC_BUF_ALIGN); | ||
502 | guard_width = ALIGN(ctx->img_width + 16, | ||
503 | S5P_FIMV_NV12MT_HALIGN); | ||
504 | guard_height = ALIGN((ctx->img_height >> 1) + 4, | ||
505 | S5P_FIMV_NV12MT_VALIGN); | ||
506 | ctx->chroma_size = ALIGN(guard_width * | ||
507 | guard_height, S5P_FIMV_DEC_BUF_ALIGN); | ||
508 | ctx->mv_size = 0; | ||
509 | } | ||
510 | ctx->dpb_count = s5p_mfc_get_dpb_count(); | ||
511 | if (ctx->img_width == 0 || ctx->img_height == 0) | 501 | if (ctx->img_width == 0 || ctx->img_height == 0) |
512 | ctx->state = MFCINST_ERROR; | 502 | ctx->state = MFCINST_ERROR; |
513 | else | 503 | else |
514 | ctx->state = MFCINST_HEAD_PARSED; | 504 | ctx->state = MFCINST_HEAD_PARSED; |
505 | |||
506 | if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | ||
507 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) && | ||
508 | !list_empty(&ctx->src_queue)) { | ||
509 | struct s5p_mfc_buf *src_buf; | ||
510 | src_buf = list_entry(ctx->src_queue.next, | ||
511 | struct s5p_mfc_buf, list); | ||
512 | if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream, | ||
513 | dev) < | ||
514 | src_buf->b->v4l2_planes[0].bytesused) | ||
515 | ctx->head_processed = 0; | ||
516 | else | ||
517 | ctx->head_processed = 1; | ||
518 | } else { | ||
519 | ctx->head_processed = 1; | ||
520 | } | ||
515 | } | 521 | } |
516 | s5p_mfc_clear_int_flags(dev); | 522 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
517 | clear_work_bit(ctx); | 523 | clear_work_bit(ctx); |
518 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 524 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) |
519 | BUG(); | 525 | BUG(); |
520 | s5p_mfc_clock_off(); | 526 | s5p_mfc_clock_off(); |
521 | s5p_mfc_try_run(dev); | 527 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
522 | wake_up_ctx(ctx, reason, err); | 528 | wake_up_ctx(ctx, reason, err); |
523 | } | 529 | } |
524 | 530 | ||
@@ -533,14 +539,14 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, | |||
533 | if (ctx == NULL) | 539 | if (ctx == NULL) |
534 | return; | 540 | return; |
535 | dev = ctx->dev; | 541 | dev = ctx->dev; |
536 | s5p_mfc_clear_int_flags(dev); | 542 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
537 | ctx->int_type = reason; | 543 | ctx->int_type = reason; |
538 | ctx->int_err = err; | 544 | ctx->int_err = err; |
539 | ctx->int_cond = 1; | 545 | ctx->int_cond = 1; |
540 | clear_work_bit(ctx); | 546 | clear_work_bit(ctx); |
541 | if (err == 0) { | 547 | if (err == 0) { |
542 | ctx->state = MFCINST_RUNNING; | 548 | ctx->state = MFCINST_RUNNING; |
543 | if (!ctx->dpb_flush_flag) { | 549 | if (!ctx->dpb_flush_flag && ctx->head_processed) { |
544 | spin_lock_irqsave(&dev->irqlock, flags); | 550 | spin_lock_irqsave(&dev->irqlock, flags); |
545 | if (!list_empty(&ctx->src_queue)) { | 551 | if (!list_empty(&ctx->src_queue)) { |
546 | src_buf = list_entry(ctx->src_queue.next, | 552 | src_buf = list_entry(ctx->src_queue.next, |
@@ -560,7 +566,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, | |||
560 | s5p_mfc_clock_off(); | 566 | s5p_mfc_clock_off(); |
561 | 567 | ||
562 | wake_up(&ctx->queue); | 568 | wake_up(&ctx->queue); |
563 | s5p_mfc_try_run(dev); | 569 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
564 | } else { | 570 | } else { |
565 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 571 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) |
566 | BUG(); | 572 | BUG(); |
@@ -602,7 +608,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, | |||
602 | 608 | ||
603 | s5p_mfc_clock_off(); | 609 | s5p_mfc_clock_off(); |
604 | wake_up(&ctx->queue); | 610 | wake_up(&ctx->queue); |
605 | s5p_mfc_try_run(dev); | 611 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
606 | } | 612 | } |
607 | 613 | ||
608 | /* Interrupt processing */ | 614 | /* Interrupt processing */ |
@@ -618,81 +624,83 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) | |||
618 | atomic_set(&dev->watchdog_cnt, 0); | 624 | atomic_set(&dev->watchdog_cnt, 0); |
619 | ctx = dev->ctx[dev->curr_ctx]; | 625 | ctx = dev->ctx[dev->curr_ctx]; |
620 | /* Get the reason of interrupt and the error code */ | 626 | /* Get the reason of interrupt and the error code */ |
621 | reason = s5p_mfc_get_int_reason(); | 627 | reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev); |
622 | err = s5p_mfc_get_int_err(); | 628 | err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev); |
623 | mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err); | 629 | mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err); |
624 | switch (reason) { | 630 | switch (reason) { |
625 | case S5P_FIMV_R2H_CMD_ERR_RET: | 631 | case S5P_MFC_R2H_CMD_ERR_RET: |
626 | /* An error has occured */ | 632 | /* An error has occured */ |
627 | if (ctx->state == MFCINST_RUNNING && | 633 | if (ctx->state == MFCINST_RUNNING && |
628 | s5p_mfc_err_dec(err) >= S5P_FIMV_ERR_WARNINGS_START) | 634 | s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >= |
635 | dev->warn_start) | ||
629 | s5p_mfc_handle_frame(ctx, reason, err); | 636 | s5p_mfc_handle_frame(ctx, reason, err); |
630 | else | 637 | else |
631 | s5p_mfc_handle_error(ctx, reason, err); | 638 | s5p_mfc_handle_error(ctx, reason, err); |
632 | clear_bit(0, &dev->enter_suspend); | 639 | clear_bit(0, &dev->enter_suspend); |
633 | break; | 640 | break; |
634 | 641 | ||
635 | case S5P_FIMV_R2H_CMD_SLICE_DONE_RET: | 642 | case S5P_MFC_R2H_CMD_SLICE_DONE_RET: |
636 | case S5P_FIMV_R2H_CMD_FRAME_DONE_RET: | 643 | case S5P_MFC_R2H_CMD_FIELD_DONE_RET: |
644 | case S5P_MFC_R2H_CMD_FRAME_DONE_RET: | ||
637 | if (ctx->c_ops->post_frame_start) { | 645 | if (ctx->c_ops->post_frame_start) { |
638 | if (ctx->c_ops->post_frame_start(ctx)) | 646 | if (ctx->c_ops->post_frame_start(ctx)) |
639 | mfc_err("post_frame_start() failed\n"); | 647 | mfc_err("post_frame_start() failed\n"); |
640 | s5p_mfc_clear_int_flags(dev); | 648 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
641 | wake_up_ctx(ctx, reason, err); | 649 | wake_up_ctx(ctx, reason, err); |
642 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 650 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) |
643 | BUG(); | 651 | BUG(); |
644 | s5p_mfc_clock_off(); | 652 | s5p_mfc_clock_off(); |
645 | s5p_mfc_try_run(dev); | 653 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
646 | } else { | 654 | } else { |
647 | s5p_mfc_handle_frame(ctx, reason, err); | 655 | s5p_mfc_handle_frame(ctx, reason, err); |
648 | } | 656 | } |
649 | break; | 657 | break; |
650 | 658 | ||
651 | case S5P_FIMV_R2H_CMD_SEQ_DONE_RET: | 659 | case S5P_MFC_R2H_CMD_SEQ_DONE_RET: |
652 | s5p_mfc_handle_seq_done(ctx, reason, err); | 660 | s5p_mfc_handle_seq_done(ctx, reason, err); |
653 | break; | 661 | break; |
654 | 662 | ||
655 | case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET: | 663 | case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET: |
656 | ctx->inst_no = s5p_mfc_get_inst_no(); | 664 | ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev); |
657 | ctx->state = MFCINST_GOT_INST; | 665 | ctx->state = MFCINST_GOT_INST; |
658 | clear_work_bit(ctx); | 666 | clear_work_bit(ctx); |
659 | wake_up(&ctx->queue); | 667 | wake_up(&ctx->queue); |
660 | goto irq_cleanup_hw; | 668 | goto irq_cleanup_hw; |
661 | 669 | ||
662 | case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET: | 670 | case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET: |
663 | clear_work_bit(ctx); | 671 | clear_work_bit(ctx); |
664 | ctx->state = MFCINST_FREE; | 672 | ctx->state = MFCINST_FREE; |
665 | wake_up(&ctx->queue); | 673 | wake_up(&ctx->queue); |
666 | goto irq_cleanup_hw; | 674 | goto irq_cleanup_hw; |
667 | 675 | ||
668 | case S5P_FIMV_R2H_CMD_SYS_INIT_RET: | 676 | case S5P_MFC_R2H_CMD_SYS_INIT_RET: |
669 | case S5P_FIMV_R2H_CMD_FW_STATUS_RET: | 677 | case S5P_MFC_R2H_CMD_FW_STATUS_RET: |
670 | case S5P_FIMV_R2H_CMD_SLEEP_RET: | 678 | case S5P_MFC_R2H_CMD_SLEEP_RET: |
671 | case S5P_FIMV_R2H_CMD_WAKEUP_RET: | 679 | case S5P_MFC_R2H_CMD_WAKEUP_RET: |
672 | if (ctx) | 680 | if (ctx) |
673 | clear_work_bit(ctx); | 681 | clear_work_bit(ctx); |
674 | s5p_mfc_clear_int_flags(dev); | 682 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
675 | wake_up_dev(dev, reason, err); | 683 | wake_up_dev(dev, reason, err); |
676 | clear_bit(0, &dev->hw_lock); | 684 | clear_bit(0, &dev->hw_lock); |
677 | clear_bit(0, &dev->enter_suspend); | 685 | clear_bit(0, &dev->enter_suspend); |
678 | break; | 686 | break; |
679 | 687 | ||
680 | case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: | 688 | case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET: |
681 | s5p_mfc_handle_init_buffers(ctx, reason, err); | 689 | s5p_mfc_handle_init_buffers(ctx, reason, err); |
682 | break; | 690 | break; |
683 | 691 | ||
684 | case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET: | 692 | case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET: |
685 | s5p_mfc_handle_stream_complete(ctx, reason, err); | 693 | s5p_mfc_handle_stream_complete(ctx, reason, err); |
686 | break; | 694 | break; |
687 | 695 | ||
688 | default: | 696 | default: |
689 | mfc_debug(2, "Unknown int reason\n"); | 697 | mfc_debug(2, "Unknown int reason\n"); |
690 | s5p_mfc_clear_int_flags(dev); | 698 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
691 | } | 699 | } |
692 | mfc_debug_leave(); | 700 | mfc_debug_leave(); |
693 | return IRQ_HANDLED; | 701 | return IRQ_HANDLED; |
694 | irq_cleanup_hw: | 702 | irq_cleanup_hw: |
695 | s5p_mfc_clear_int_flags(dev); | 703 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
696 | ctx->int_type = reason; | 704 | ctx->int_type = reason; |
697 | ctx->int_err = err; | 705 | ctx->int_err = err; |
698 | ctx->int_cond = 1; | 706 | ctx->int_cond = 1; |
@@ -701,7 +709,7 @@ irq_cleanup_hw: | |||
701 | 709 | ||
702 | s5p_mfc_clock_off(); | 710 | s5p_mfc_clock_off(); |
703 | 711 | ||
704 | s5p_mfc_try_run(dev); | 712 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
705 | mfc_debug(2, "Exit via irq_cleanup_hw\n"); | 713 | mfc_debug(2, "Exit via irq_cleanup_hw\n"); |
706 | return IRQ_HANDLED; | 714 | return IRQ_HANDLED; |
707 | } | 715 | } |
@@ -749,6 +757,7 @@ static int s5p_mfc_open(struct file *file) | |||
749 | if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { | 757 | if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { |
750 | ctx->type = MFCINST_DECODER; | 758 | ctx->type = MFCINST_DECODER; |
751 | ctx->c_ops = get_dec_codec_ops(); | 759 | ctx->c_ops = get_dec_codec_ops(); |
760 | s5p_mfc_dec_init(ctx); | ||
752 | /* Setup ctrl handler */ | 761 | /* Setup ctrl handler */ |
753 | ret = s5p_mfc_dec_ctrls_setup(ctx); | 762 | ret = s5p_mfc_dec_ctrls_setup(ctx); |
754 | if (ret) { | 763 | if (ret) { |
@@ -761,6 +770,7 @@ static int s5p_mfc_open(struct file *file) | |||
761 | /* only for encoder */ | 770 | /* only for encoder */ |
762 | INIT_LIST_HEAD(&ctx->ref_queue); | 771 | INIT_LIST_HEAD(&ctx->ref_queue); |
763 | ctx->ref_queue_cnt = 0; | 772 | ctx->ref_queue_cnt = 0; |
773 | s5p_mfc_enc_init(ctx); | ||
764 | /* Setup ctrl handler */ | 774 | /* Setup ctrl handler */ |
765 | ret = s5p_mfc_enc_ctrls_setup(ctx); | 775 | ret = s5p_mfc_enc_ctrls_setup(ctx); |
766 | if (ret) { | 776 | if (ret) { |
@@ -886,19 +896,20 @@ static int s5p_mfc_release(struct file *file) | |||
886 | ctx->state = MFCINST_RETURN_INST; | 896 | ctx->state = MFCINST_RETURN_INST; |
887 | set_work_bit_irqsave(ctx); | 897 | set_work_bit_irqsave(ctx); |
888 | s5p_mfc_clean_ctx_int_flags(ctx); | 898 | s5p_mfc_clean_ctx_int_flags(ctx); |
889 | s5p_mfc_try_run(dev); | 899 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
890 | /* Wait until instance is returned or timeout occured */ | 900 | /* Wait until instance is returned or timeout occured */ |
891 | if (s5p_mfc_wait_for_done_ctx | 901 | if (s5p_mfc_wait_for_done_ctx |
892 | (ctx, S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET, 0)) { | 902 | (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) { |
893 | s5p_mfc_clock_off(); | 903 | s5p_mfc_clock_off(); |
894 | mfc_err("Err returning instance\n"); | 904 | mfc_err("Err returning instance\n"); |
895 | } | 905 | } |
896 | mfc_debug(2, "After free instance\n"); | 906 | mfc_debug(2, "After free instance\n"); |
897 | /* Free resources */ | 907 | /* Free resources */ |
898 | s5p_mfc_release_codec_buffers(ctx); | 908 | s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); |
899 | s5p_mfc_release_instance_buffer(ctx); | 909 | s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); |
900 | if (ctx->type == MFCINST_DECODER) | 910 | if (ctx->type == MFCINST_DECODER) |
901 | s5p_mfc_release_dec_desc_buffer(ctx); | 911 | s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, |
912 | ctx); | ||
902 | 913 | ||
903 | ctx->inst_no = MFC_NO_INSTANCE_SET; | 914 | ctx->inst_no = MFC_NO_INSTANCE_SET; |
904 | } | 915 | } |
@@ -910,6 +921,7 @@ static int s5p_mfc_release(struct file *file) | |||
910 | mfc_debug(2, "Last instance - release firmware\n"); | 921 | mfc_debug(2, "Last instance - release firmware\n"); |
911 | /* reset <-> F/W release */ | 922 | /* reset <-> F/W release */ |
912 | s5p_mfc_reset(dev); | 923 | s5p_mfc_reset(dev); |
924 | s5p_mfc_deinit_hw(dev); | ||
913 | s5p_mfc_release_firmware(dev); | 925 | s5p_mfc_release_firmware(dev); |
914 | del_timer_sync(&dev->watchdog_timer); | 926 | del_timer_sync(&dev->watchdog_timer); |
915 | if (s5p_mfc_power_off() < 0) | 927 | if (s5p_mfc_power_off() < 0) |
@@ -1041,6 +1053,9 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1041 | return -ENODEV; | 1053 | return -ENODEV; |
1042 | } | 1054 | } |
1043 | 1055 | ||
1056 | dev->variant = (struct s5p_mfc_variant *) | ||
1057 | platform_get_device_id(pdev)->driver_data; | ||
1058 | |||
1044 | ret = s5p_mfc_init_pm(dev); | 1059 | ret = s5p_mfc_init_pm(dev); |
1045 | if (ret < 0) { | 1060 | if (ret < 0) { |
1046 | dev_err(&pdev->dev, "failed to get mfc clock source\n"); | 1061 | dev_err(&pdev->dev, "failed to get mfc clock source\n"); |
@@ -1076,6 +1091,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1076 | ret = -ENODEV; | 1091 | ret = -ENODEV; |
1077 | goto err_res; | 1092 | goto err_res; |
1078 | } | 1093 | } |
1094 | |||
1079 | dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r", | 1095 | dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r", |
1080 | match_child); | 1096 | match_child); |
1081 | if (!dev->mem_dev_r) { | 1097 | if (!dev->mem_dev_r) { |
@@ -1139,6 +1155,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1139 | vfd->release = video_device_release, | 1155 | vfd->release = video_device_release, |
1140 | vfd->lock = &dev->mfc_mutex; | 1156 | vfd->lock = &dev->mfc_mutex; |
1141 | vfd->v4l2_dev = &dev->v4l2_dev; | 1157 | vfd->v4l2_dev = &dev->v4l2_dev; |
1158 | vfd->vfl_dir = VFL_DIR_M2M; | ||
1142 | snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME); | 1159 | snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME); |
1143 | dev->vfd_enc = vfd; | 1160 | dev->vfd_enc = vfd; |
1144 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | 1161 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); |
@@ -1160,6 +1177,10 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1160 | dev->watchdog_timer.data = (unsigned long)dev; | 1177 | dev->watchdog_timer.data = (unsigned long)dev; |
1161 | dev->watchdog_timer.function = s5p_mfc_watchdog; | 1178 | dev->watchdog_timer.function = s5p_mfc_watchdog; |
1162 | 1179 | ||
1180 | /* Initialize HW ops and commands based on MFC version */ | ||
1181 | s5p_mfc_init_hw_ops(dev); | ||
1182 | s5p_mfc_init_hw_cmds(dev); | ||
1183 | |||
1163 | pr_debug("%s--\n", __func__); | 1184 | pr_debug("%s--\n", __func__); |
1164 | return 0; | 1185 | return 0; |
1165 | 1186 | ||
@@ -1280,9 +1301,78 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = { | |||
1280 | NULL) | 1301 | NULL) |
1281 | }; | 1302 | }; |
1282 | 1303 | ||
1304 | struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = { | ||
1305 | .h264_ctx = MFC_H264_CTX_BUF_SIZE, | ||
1306 | .non_h264_ctx = MFC_CTX_BUF_SIZE, | ||
1307 | .dsc = DESC_BUF_SIZE, | ||
1308 | .shm = SHARED_BUF_SIZE, | ||
1309 | }; | ||
1310 | |||
1311 | struct s5p_mfc_buf_size buf_size_v5 = { | ||
1312 | .fw = MAX_FW_SIZE, | ||
1313 | .cpb = MAX_CPB_SIZE, | ||
1314 | .priv = &mfc_buf_size_v5, | ||
1315 | }; | ||
1316 | |||
1317 | struct s5p_mfc_buf_align mfc_buf_align_v5 = { | ||
1318 | .base = MFC_BASE_ALIGN_ORDER, | ||
1319 | }; | ||
1320 | |||
1321 | static struct s5p_mfc_variant mfc_drvdata_v5 = { | ||
1322 | .version = MFC_VERSION, | ||
1323 | .port_num = MFC_NUM_PORTS, | ||
1324 | .buf_size = &buf_size_v5, | ||
1325 | .buf_align = &mfc_buf_align_v5, | ||
1326 | .mclk_name = "sclk_mfc", | ||
1327 | .fw_name = "s5p-mfc.fw", | ||
1328 | }; | ||
1329 | |||
1330 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = { | ||
1331 | .dev_ctx = MFC_CTX_BUF_SIZE_V6, | ||
1332 | .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V6, | ||
1333 | .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V6, | ||
1334 | .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V6, | ||
1335 | .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V6, | ||
1336 | }; | ||
1337 | |||
1338 | struct s5p_mfc_buf_size buf_size_v6 = { | ||
1339 | .fw = MAX_FW_SIZE_V6, | ||
1340 | .cpb = MAX_CPB_SIZE_V6, | ||
1341 | .priv = &mfc_buf_size_v6, | ||
1342 | }; | ||
1343 | |||
1344 | struct s5p_mfc_buf_align mfc_buf_align_v6 = { | ||
1345 | .base = 0, | ||
1346 | }; | ||
1347 | |||
1348 | static struct s5p_mfc_variant mfc_drvdata_v6 = { | ||
1349 | .version = MFC_VERSION_V6, | ||
1350 | .port_num = MFC_NUM_PORTS_V6, | ||
1351 | .buf_size = &buf_size_v6, | ||
1352 | .buf_align = &mfc_buf_align_v6, | ||
1353 | .mclk_name = "aclk_333", | ||
1354 | .fw_name = "s5p-mfc-v6.fw", | ||
1355 | }; | ||
1356 | |||
1357 | static struct platform_device_id mfc_driver_ids[] = { | ||
1358 | { | ||
1359 | .name = "s5p-mfc", | ||
1360 | .driver_data = (unsigned long)&mfc_drvdata_v5, | ||
1361 | }, { | ||
1362 | .name = "s5p-mfc-v5", | ||
1363 | .driver_data = (unsigned long)&mfc_drvdata_v5, | ||
1364 | }, { | ||
1365 | .name = "s5p-mfc-v6", | ||
1366 | .driver_data = (unsigned long)&mfc_drvdata_v6, | ||
1367 | }, | ||
1368 | {}, | ||
1369 | }; | ||
1370 | MODULE_DEVICE_TABLE(platform, mfc_driver_ids); | ||
1371 | |||
1283 | static struct platform_driver s5p_mfc_driver = { | 1372 | static struct platform_driver s5p_mfc_driver = { |
1284 | .probe = s5p_mfc_probe, | 1373 | .probe = s5p_mfc_probe, |
1285 | .remove = __devexit_p(s5p_mfc_remove), | 1374 | .remove = __devexit_p(s5p_mfc_remove), |
1375 | .id_table = mfc_driver_ids, | ||
1286 | .driver = { | 1376 | .driver = { |
1287 | .name = S5P_MFC_NAME, | 1377 | .name = S5P_MFC_NAME, |
1288 | .owner = THIS_MODULE, | 1378 | .owner = THIS_MODULE, |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c index 91a415573bd2..f0a41c95df84 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | 2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | 4 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 5 | * http://www.samsung.com/ |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -10,111 +10,20 @@ | |||
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "regs-mfc.h" | ||
14 | #include "s5p_mfc_cmd.h" | 13 | #include "s5p_mfc_cmd.h" |
15 | #include "s5p_mfc_common.h" | 14 | #include "s5p_mfc_common.h" |
16 | #include "s5p_mfc_debug.h" | 15 | #include "s5p_mfc_debug.h" |
16 | #include "s5p_mfc_cmd_v5.h" | ||
17 | #include "s5p_mfc_cmd_v6.h" | ||
17 | 18 | ||
18 | /* This function is used to send a command to the MFC */ | 19 | static struct s5p_mfc_hw_cmds *s5p_mfc_cmds; |
19 | static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd, | ||
20 | struct s5p_mfc_cmd_args *args) | ||
21 | { | ||
22 | int cur_cmd; | ||
23 | unsigned long timeout; | ||
24 | |||
25 | timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); | ||
26 | /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */ | ||
27 | do { | ||
28 | if (time_after(jiffies, timeout)) { | ||
29 | mfc_err("Timeout while waiting for hardware\n"); | ||
30 | return -EIO; | ||
31 | } | ||
32 | cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD); | ||
33 | } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY); | ||
34 | mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1); | ||
35 | mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2); | ||
36 | mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3); | ||
37 | mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4); | ||
38 | /* Issue the command */ | ||
39 | mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | /* Initialize the MFC */ | ||
44 | int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev) | ||
45 | { | ||
46 | struct s5p_mfc_cmd_args h2r_args; | ||
47 | |||
48 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
49 | h2r_args.arg[0] = dev->fw_size; | ||
50 | return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args); | ||
51 | } | ||
52 | |||
53 | /* Suspend the MFC hardware */ | ||
54 | int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev) | ||
55 | { | ||
56 | struct s5p_mfc_cmd_args h2r_args; | ||
57 | |||
58 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
59 | return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args); | ||
60 | } | ||
61 | 20 | ||
62 | /* Wake up the MFC hardware */ | 21 | void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) |
63 | int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev) | ||
64 | { | 22 | { |
65 | struct s5p_mfc_cmd_args h2r_args; | 23 | if (IS_MFCV6(dev)) |
24 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); | ||
25 | else | ||
26 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); | ||
66 | 27 | ||
67 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | 28 | dev->mfc_cmds = s5p_mfc_cmds; |
68 | return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args); | ||
69 | } | 29 | } |
70 | |||
71 | |||
72 | int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx) | ||
73 | { | ||
74 | struct s5p_mfc_dev *dev = ctx->dev; | ||
75 | struct s5p_mfc_cmd_args h2r_args; | ||
76 | int ret; | ||
77 | |||
78 | /* Preparing decoding - getting instance number */ | ||
79 | mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode); | ||
80 | dev->curr_ctx = ctx->num; | ||
81 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
82 | h2r_args.arg[0] = ctx->codec_mode; | ||
83 | h2r_args.arg[1] = 0; /* no crc & no pixelcache */ | ||
84 | h2r_args.arg[2] = ctx->ctx_ofs; | ||
85 | h2r_args.arg[3] = ctx->ctx_size; | ||
86 | ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE, | ||
87 | &h2r_args); | ||
88 | if (ret) { | ||
89 | mfc_err("Failed to create a new instance\n"); | ||
90 | ctx->state = MFCINST_ERROR; | ||
91 | } | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx) | ||
96 | { | ||
97 | struct s5p_mfc_dev *dev = ctx->dev; | ||
98 | struct s5p_mfc_cmd_args h2r_args; | ||
99 | int ret; | ||
100 | |||
101 | if (ctx->state == MFCINST_FREE) { | ||
102 | mfc_err("Instance already returned\n"); | ||
103 | ctx->state = MFCINST_ERROR; | ||
104 | return -EINVAL; | ||
105 | } | ||
106 | /* Closing decoding instance */ | ||
107 | mfc_debug(2, "Returning instance number %d\n", ctx->inst_no); | ||
108 | dev->curr_ctx = ctx->num; | ||
109 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
110 | h2r_args.arg[0] = ctx->inst_no; | ||
111 | ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE, | ||
112 | &h2r_args); | ||
113 | if (ret) { | ||
114 | mfc_err("Failed to return an instance\n"); | ||
115 | ctx->state = MFCINST_ERROR; | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h index 8b090d3723e7..282e6c780702 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h | 2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | 4 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 5 | * http://www.samsung.com/ |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -21,10 +21,15 @@ struct s5p_mfc_cmd_args { | |||
21 | unsigned int arg[MAX_H2R_ARG]; | 21 | unsigned int arg[MAX_H2R_ARG]; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev); | 24 | struct s5p_mfc_hw_cmds { |
25 | int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev); | 25 | int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd, |
26 | int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev); | 26 | struct s5p_mfc_cmd_args *args); |
27 | int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx); | 27 | int (*sys_init_cmd)(struct s5p_mfc_dev *dev); |
28 | int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx); | 28 | int (*sleep_cmd)(struct s5p_mfc_dev *dev); |
29 | int (*wakeup_cmd)(struct s5p_mfc_dev *dev); | ||
30 | int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx); | ||
31 | int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx); | ||
32 | }; | ||
29 | 33 | ||
34 | void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev); | ||
30 | #endif /* S5P_MFC_CMD_H_ */ | 35 | #endif /* S5P_MFC_CMD_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c new file mode 100644 index 000000000000..138778083c63 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include "regs-mfc.h" | ||
14 | #include "s5p_mfc_cmd.h" | ||
15 | #include "s5p_mfc_common.h" | ||
16 | #include "s5p_mfc_debug.h" | ||
17 | |||
18 | /* This function is used to send a command to the MFC */ | ||
19 | int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd, | ||
20 | struct s5p_mfc_cmd_args *args) | ||
21 | { | ||
22 | int cur_cmd; | ||
23 | unsigned long timeout; | ||
24 | |||
25 | timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); | ||
26 | /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */ | ||
27 | do { | ||
28 | if (time_after(jiffies, timeout)) { | ||
29 | mfc_err("Timeout while waiting for hardware\n"); | ||
30 | return -EIO; | ||
31 | } | ||
32 | cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD); | ||
33 | } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY); | ||
34 | mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1); | ||
35 | mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2); | ||
36 | mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3); | ||
37 | mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4); | ||
38 | /* Issue the command */ | ||
39 | mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | /* Initialize the MFC */ | ||
44 | int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) | ||
45 | { | ||
46 | struct s5p_mfc_cmd_args h2r_args; | ||
47 | |||
48 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
49 | h2r_args.arg[0] = dev->fw_size; | ||
50 | return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT, | ||
51 | &h2r_args); | ||
52 | } | ||
53 | |||
54 | /* Suspend the MFC hardware */ | ||
55 | int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev) | ||
56 | { | ||
57 | struct s5p_mfc_cmd_args h2r_args; | ||
58 | |||
59 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
60 | return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args); | ||
61 | } | ||
62 | |||
63 | /* Wake up the MFC hardware */ | ||
64 | int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev) | ||
65 | { | ||
66 | struct s5p_mfc_cmd_args h2r_args; | ||
67 | |||
68 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
69 | return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP, | ||
70 | &h2r_args); | ||
71 | } | ||
72 | |||
73 | |||
74 | int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx) | ||
75 | { | ||
76 | struct s5p_mfc_dev *dev = ctx->dev; | ||
77 | struct s5p_mfc_cmd_args h2r_args; | ||
78 | int ret; | ||
79 | |||
80 | /* Preparing decoding - getting instance number */ | ||
81 | mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode); | ||
82 | dev->curr_ctx = ctx->num; | ||
83 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
84 | switch (ctx->codec_mode) { | ||
85 | case S5P_MFC_CODEC_H264_DEC: | ||
86 | h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC; | ||
87 | break; | ||
88 | case S5P_MFC_CODEC_VC1_DEC: | ||
89 | h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC; | ||
90 | break; | ||
91 | case S5P_MFC_CODEC_MPEG4_DEC: | ||
92 | h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC; | ||
93 | break; | ||
94 | case S5P_MFC_CODEC_MPEG2_DEC: | ||
95 | h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC; | ||
96 | break; | ||
97 | case S5P_MFC_CODEC_H263_DEC: | ||
98 | h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC; | ||
99 | break; | ||
100 | case S5P_MFC_CODEC_VC1RCV_DEC: | ||
101 | h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC; | ||
102 | break; | ||
103 | case S5P_MFC_CODEC_H264_ENC: | ||
104 | h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC; | ||
105 | break; | ||
106 | case S5P_MFC_CODEC_MPEG4_ENC: | ||
107 | h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC; | ||
108 | break; | ||
109 | case S5P_MFC_CODEC_H263_ENC: | ||
110 | h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC; | ||
111 | break; | ||
112 | default: | ||
113 | h2r_args.arg[0] = S5P_FIMV_CODEC_NONE; | ||
114 | }; | ||
115 | h2r_args.arg[1] = 0; /* no crc & no pixelcache */ | ||
116 | h2r_args.arg[2] = ctx->ctx.ofs; | ||
117 | h2r_args.arg[3] = ctx->ctx.size; | ||
118 | ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE, | ||
119 | &h2r_args); | ||
120 | if (ret) { | ||
121 | mfc_err("Failed to create a new instance\n"); | ||
122 | ctx->state = MFCINST_ERROR; | ||
123 | } | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx) | ||
128 | { | ||
129 | struct s5p_mfc_dev *dev = ctx->dev; | ||
130 | struct s5p_mfc_cmd_args h2r_args; | ||
131 | int ret; | ||
132 | |||
133 | if (ctx->state == MFCINST_FREE) { | ||
134 | mfc_err("Instance already returned\n"); | ||
135 | ctx->state = MFCINST_ERROR; | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | /* Closing decoding instance */ | ||
139 | mfc_debug(2, "Returning instance number %d\n", ctx->inst_no); | ||
140 | dev->curr_ctx = ctx->num; | ||
141 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
142 | h2r_args.arg[0] = ctx->inst_no; | ||
143 | ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE, | ||
144 | &h2r_args); | ||
145 | if (ret) { | ||
146 | mfc_err("Failed to return an instance\n"); | ||
147 | ctx->state = MFCINST_ERROR; | ||
148 | return -EINVAL; | ||
149 | } | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* Initialize cmd function pointers for MFC v5 */ | ||
154 | static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = { | ||
155 | .cmd_host2risc = s5p_mfc_cmd_host2risc_v5, | ||
156 | .sys_init_cmd = s5p_mfc_sys_init_cmd_v5, | ||
157 | .sleep_cmd = s5p_mfc_sleep_cmd_v5, | ||
158 | .wakeup_cmd = s5p_mfc_wakeup_cmd_v5, | ||
159 | .open_inst_cmd = s5p_mfc_open_inst_cmd_v5, | ||
160 | .close_inst_cmd = s5p_mfc_close_inst_cmd_v5, | ||
161 | }; | ||
162 | |||
163 | struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void) | ||
164 | { | ||
165 | return &s5p_mfc_cmds_v5; | ||
166 | } | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h new file mode 100644 index 000000000000..6928a5514c1b --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef S5P_MFC_CMD_V5_H_ | ||
14 | #define S5P_MFC_CMD_V5_H_ | ||
15 | |||
16 | #include "s5p_mfc_common.h" | ||
17 | |||
18 | struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void); | ||
19 | |||
20 | #endif /* S5P_MFC_CMD_H_ */ | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c new file mode 100644 index 000000000000..754bfbcb1c43 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | ||
3 | * | ||
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include "s5p_mfc_common.h" | ||
14 | |||
15 | #include "s5p_mfc_cmd.h" | ||
16 | #include "s5p_mfc_debug.h" | ||
17 | #include "s5p_mfc_intr.h" | ||
18 | #include "s5p_mfc_opr.h" | ||
19 | |||
20 | int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, | ||
21 | struct s5p_mfc_cmd_args *args) | ||
22 | { | ||
23 | mfc_debug(2, "Issue the command: %d\n", cmd); | ||
24 | |||
25 | /* Reset RISC2HOST command */ | ||
26 | mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6); | ||
27 | |||
28 | /* Issue the command */ | ||
29 | mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6); | ||
30 | mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6); | ||
31 | |||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) | ||
36 | { | ||
37 | struct s5p_mfc_cmd_args h2r_args; | ||
38 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | ||
39 | |||
40 | s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev); | ||
41 | mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6); | ||
42 | mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6); | ||
43 | return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6, | ||
44 | &h2r_args); | ||
45 | } | ||
46 | |||
47 | int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev) | ||
48 | { | ||
49 | struct s5p_mfc_cmd_args h2r_args; | ||
50 | |||
51 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
52 | return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6, | ||
53 | &h2r_args); | ||
54 | } | ||
55 | |||
56 | int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev) | ||
57 | { | ||
58 | struct s5p_mfc_cmd_args h2r_args; | ||
59 | |||
60 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | ||
61 | return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6, | ||
62 | &h2r_args); | ||
63 | } | ||
64 | |||
65 | /* Open a new instance and get its number */ | ||
66 | int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) | ||
67 | { | ||
68 | struct s5p_mfc_dev *dev = ctx->dev; | ||
69 | struct s5p_mfc_cmd_args h2r_args; | ||
70 | int codec_type; | ||
71 | |||
72 | mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode); | ||
73 | dev->curr_ctx = ctx->num; | ||
74 | switch (ctx->codec_mode) { | ||
75 | case S5P_MFC_CODEC_H264_DEC: | ||
76 | codec_type = S5P_FIMV_CODEC_H264_DEC_V6; | ||
77 | break; | ||
78 | case S5P_MFC_CODEC_H264_MVC_DEC: | ||
79 | codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6; | ||
80 | break; | ||
81 | case S5P_MFC_CODEC_VC1_DEC: | ||
82 | codec_type = S5P_FIMV_CODEC_VC1_DEC_V6; | ||
83 | break; | ||
84 | case S5P_MFC_CODEC_MPEG4_DEC: | ||
85 | codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6; | ||
86 | break; | ||
87 | case S5P_MFC_CODEC_MPEG2_DEC: | ||
88 | codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6; | ||
89 | break; | ||
90 | case S5P_MFC_CODEC_H263_DEC: | ||
91 | codec_type = S5P_FIMV_CODEC_H263_DEC_V6; | ||
92 | break; | ||
93 | case S5P_MFC_CODEC_VC1RCV_DEC: | ||
94 | codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6; | ||
95 | break; | ||
96 | case S5P_MFC_CODEC_VP8_DEC: | ||
97 | codec_type = S5P_FIMV_CODEC_VP8_DEC_V6; | ||
98 | break; | ||
99 | case S5P_MFC_CODEC_H264_ENC: | ||
100 | codec_type = S5P_FIMV_CODEC_H264_ENC_V6; | ||
101 | break; | ||
102 | case S5P_MFC_CODEC_H264_MVC_ENC: | ||
103 | codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6; | ||
104 | break; | ||
105 | case S5P_MFC_CODEC_MPEG4_ENC: | ||
106 | codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6; | ||
107 | break; | ||
108 | case S5P_MFC_CODEC_H263_ENC: | ||
109 | codec_type = S5P_FIMV_CODEC_H263_ENC_V6; | ||
110 | break; | ||
111 | default: | ||
112 | codec_type = S5P_FIMV_CODEC_NONE_V6; | ||
113 | }; | ||
114 | mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6); | ||
115 | mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6); | ||
116 | mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); | ||
117 | mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */ | ||
118 | |||
119 | return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6, | ||
120 | &h2r_args); | ||
121 | } | ||
122 | |||
123 | /* Close instance */ | ||
124 | int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) | ||
125 | { | ||
126 | struct s5p_mfc_dev *dev = ctx->dev; | ||
127 | struct s5p_mfc_cmd_args h2r_args; | ||
128 | int ret = 0; | ||
129 | |||
130 | dev->curr_ctx = ctx->num; | ||
131 | if (ctx->state != MFCINST_FREE) { | ||
132 | mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
133 | ret = s5p_mfc_cmd_host2risc_v6(dev, | ||
134 | S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6, | ||
135 | &h2r_args); | ||
136 | } else { | ||
137 | ret = -EINVAL; | ||
138 | } | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | /* Initialize cmd function pointers for MFC v6 */ | ||
144 | static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = { | ||
145 | .cmd_host2risc = s5p_mfc_cmd_host2risc_v6, | ||
146 | .sys_init_cmd = s5p_mfc_sys_init_cmd_v6, | ||
147 | .sleep_cmd = s5p_mfc_sleep_cmd_v6, | ||
148 | .wakeup_cmd = s5p_mfc_wakeup_cmd_v6, | ||
149 | .open_inst_cmd = s5p_mfc_open_inst_cmd_v6, | ||
150 | .close_inst_cmd = s5p_mfc_close_inst_cmd_v6, | ||
151 | }; | ||
152 | |||
153 | struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void) | ||
154 | { | ||
155 | return &s5p_mfc_cmds_v6; | ||
156 | } | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h new file mode 100644 index 000000000000..b7a8e57837b5 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef S5P_MFC_CMD_V6_H_ | ||
14 | #define S5P_MFC_CMD_V6_H_ | ||
15 | |||
16 | #include "s5p_mfc_common.h" | ||
17 | |||
18 | struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void); | ||
19 | |||
20 | #endif /* S5P_MFC_CMD_H_ */ | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 519b0d66d8d1..f02e0497ca98 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h | |||
@@ -16,13 +16,14 @@ | |||
16 | #ifndef S5P_MFC_COMMON_H_ | 16 | #ifndef S5P_MFC_COMMON_H_ |
17 | #define S5P_MFC_COMMON_H_ | 17 | #define S5P_MFC_COMMON_H_ |
18 | 18 | ||
19 | #include "regs-mfc.h" | ||
20 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
21 | #include <linux/videodev2.h> | 20 | #include <linux/videodev2.h> |
22 | #include <media/v4l2-ctrls.h> | 21 | #include <media/v4l2-ctrls.h> |
23 | #include <media/v4l2-device.h> | 22 | #include <media/v4l2-device.h> |
24 | #include <media/v4l2-ioctl.h> | 23 | #include <media/v4l2-ioctl.h> |
25 | #include <media/videobuf2-core.h> | 24 | #include <media/videobuf2-core.h> |
25 | #include "regs-mfc.h" | ||
26 | #include "regs-mfc-v6.h" | ||
26 | 27 | ||
27 | /* Definitions related to MFC memory */ | 28 | /* Definitions related to MFC memory */ |
28 | 29 | ||
@@ -30,17 +31,6 @@ | |||
30 | * while mmaping */ | 31 | * while mmaping */ |
31 | #define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) | 32 | #define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) |
32 | 33 | ||
33 | /* Offset used by the hardware to store addresses */ | ||
34 | #define MFC_OFFSET_SHIFT 11 | ||
35 | |||
36 | #define FIRMWARE_ALIGN 0x20000 /* 128KB */ | ||
37 | #define MFC_H264_CTX_BUF_SIZE 0x96000 /* 600KB per H264 instance */ | ||
38 | #define MFC_CTX_BUF_SIZE 0x2800 /* 10KB per instance */ | ||
39 | #define DESC_BUF_SIZE 0x20000 /* 128KB for DESC buffer */ | ||
40 | #define SHARED_BUF_SIZE 0x2000 /* 8KB for shared buffer */ | ||
41 | |||
42 | #define DEF_CPB_SIZE 0x40000 /* 512KB */ | ||
43 | |||
44 | #define MFC_BANK1_ALLOC_CTX 0 | 34 | #define MFC_BANK1_ALLOC_CTX 0 |
45 | #define MFC_BANK2_ALLOC_CTX 1 | 35 | #define MFC_BANK2_ALLOC_CTX 1 |
46 | 36 | ||
@@ -74,7 +64,40 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) | |||
74 | #define MFC_ENC_CAP_PLANE_COUNT 1 | 64 | #define MFC_ENC_CAP_PLANE_COUNT 1 |
75 | #define MFC_ENC_OUT_PLANE_COUNT 2 | 65 | #define MFC_ENC_OUT_PLANE_COUNT 2 |
76 | #define STUFF_BYTE 4 | 66 | #define STUFF_BYTE 4 |
77 | #define MFC_MAX_CTRLS 64 | 67 | #define MFC_MAX_CTRLS 70 |
68 | |||
69 | #define S5P_MFC_CODEC_NONE -1 | ||
70 | #define S5P_MFC_CODEC_H264_DEC 0 | ||
71 | #define S5P_MFC_CODEC_H264_MVC_DEC 1 | ||
72 | #define S5P_MFC_CODEC_VC1_DEC 2 | ||
73 | #define S5P_MFC_CODEC_MPEG4_DEC 3 | ||
74 | #define S5P_MFC_CODEC_MPEG2_DEC 4 | ||
75 | #define S5P_MFC_CODEC_H263_DEC 5 | ||
76 | #define S5P_MFC_CODEC_VC1RCV_DEC 6 | ||
77 | #define S5P_MFC_CODEC_VP8_DEC 7 | ||
78 | |||
79 | #define S5P_MFC_CODEC_H264_ENC 20 | ||
80 | #define S5P_MFC_CODEC_H264_MVC_ENC 21 | ||
81 | #define S5P_MFC_CODEC_MPEG4_ENC 22 | ||
82 | #define S5P_MFC_CODEC_H263_ENC 23 | ||
83 | |||
84 | #define S5P_MFC_R2H_CMD_EMPTY 0 | ||
85 | #define S5P_MFC_R2H_CMD_SYS_INIT_RET 1 | ||
86 | #define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET 2 | ||
87 | #define S5P_MFC_R2H_CMD_SEQ_DONE_RET 3 | ||
88 | #define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET 4 | ||
89 | #define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET 6 | ||
90 | #define S5P_MFC_R2H_CMD_SLEEP_RET 7 | ||
91 | #define S5P_MFC_R2H_CMD_WAKEUP_RET 8 | ||
92 | #define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET 9 | ||
93 | #define S5P_MFC_R2H_CMD_DPB_FLUSH_RET 10 | ||
94 | #define S5P_MFC_R2H_CMD_NAL_ABORT_RET 11 | ||
95 | #define S5P_MFC_R2H_CMD_FW_STATUS_RET 12 | ||
96 | #define S5P_MFC_R2H_CMD_FRAME_DONE_RET 13 | ||
97 | #define S5P_MFC_R2H_CMD_FIELD_DONE_RET 14 | ||
98 | #define S5P_MFC_R2H_CMD_SLICE_DONE_RET 15 | ||
99 | #define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET 16 | ||
100 | #define S5P_MFC_R2H_CMD_ERR_RET 32 | ||
78 | 101 | ||
79 | #define mfc_read(dev, offset) readl(dev->regs_base + (offset)) | 102 | #define mfc_read(dev, offset) readl(dev->regs_base + (offset)) |
80 | #define mfc_write(dev, data, offset) writel((data), dev->regs_base + \ | 103 | #define mfc_write(dev, data, offset) writel((data), dev->regs_base + \ |
@@ -177,6 +200,58 @@ struct s5p_mfc_pm { | |||
177 | struct device *device; | 200 | struct device *device; |
178 | }; | 201 | }; |
179 | 202 | ||
203 | struct s5p_mfc_buf_size_v5 { | ||
204 | unsigned int h264_ctx; | ||
205 | unsigned int non_h264_ctx; | ||
206 | unsigned int dsc; | ||
207 | unsigned int shm; | ||
208 | }; | ||
209 | |||
210 | struct s5p_mfc_buf_size_v6 { | ||
211 | unsigned int dev_ctx; | ||
212 | unsigned int h264_dec_ctx; | ||
213 | unsigned int other_dec_ctx; | ||
214 | unsigned int h264_enc_ctx; | ||
215 | unsigned int other_enc_ctx; | ||
216 | }; | ||
217 | |||
218 | struct s5p_mfc_buf_size { | ||
219 | unsigned int fw; | ||
220 | unsigned int cpb; | ||
221 | void *priv; | ||
222 | }; | ||
223 | |||
224 | struct s5p_mfc_buf_align { | ||
225 | unsigned int base; | ||
226 | }; | ||
227 | |||
228 | struct s5p_mfc_variant { | ||
229 | unsigned int version; | ||
230 | unsigned int port_num; | ||
231 | struct s5p_mfc_buf_size *buf_size; | ||
232 | struct s5p_mfc_buf_align *buf_align; | ||
233 | char *mclk_name; | ||
234 | char *fw_name; | ||
235 | }; | ||
236 | |||
237 | /** | ||
238 | * struct s5p_mfc_priv_buf - represents internal used buffer | ||
239 | * @alloc: allocation-specific context for each buffer | ||
240 | * (videobuf2 allocator) | ||
241 | * @ofs: offset of each buffer, will be used for MFC | ||
242 | * @virt: kernel virtual address, only valid when the | ||
243 | * buffer accessed by driver | ||
244 | * @dma: DMA address, only valid when kernel DMA API used | ||
245 | * @size: size of the buffer | ||
246 | */ | ||
247 | struct s5p_mfc_priv_buf { | ||
248 | void *alloc; | ||
249 | unsigned long ofs; | ||
250 | void *virt; | ||
251 | dma_addr_t dma; | ||
252 | size_t size; | ||
253 | }; | ||
254 | |||
180 | /** | 255 | /** |
181 | * struct s5p_mfc_dev - The struct containing driver internal parameters. | 256 | * struct s5p_mfc_dev - The struct containing driver internal parameters. |
182 | * | 257 | * |
@@ -191,6 +266,7 @@ struct s5p_mfc_pm { | |||
191 | * @dec_ctrl_handler: control framework handler for decoding | 266 | * @dec_ctrl_handler: control framework handler for decoding |
192 | * @enc_ctrl_handler: control framework handler for encoding | 267 | * @enc_ctrl_handler: control framework handler for encoding |
193 | * @pm: power management control | 268 | * @pm: power management control |
269 | * @variant: MFC hardware variant information | ||
194 | * @num_inst: couter of active MFC instances | 270 | * @num_inst: couter of active MFC instances |
195 | * @irqlock: lock for operations on videobuf2 queues | 271 | * @irqlock: lock for operations on videobuf2 queues |
196 | * @condlock: lock for changing/checking if a context is ready to be | 272 | * @condlock: lock for changing/checking if a context is ready to be |
@@ -212,6 +288,10 @@ struct s5p_mfc_pm { | |||
212 | * @watchdog_work: worker for the watchdog | 288 | * @watchdog_work: worker for the watchdog |
213 | * @alloc_ctx: videobuf2 allocator contexts for two memory banks | 289 | * @alloc_ctx: videobuf2 allocator contexts for two memory banks |
214 | * @enter_suspend: flag set when entering suspend | 290 | * @enter_suspend: flag set when entering suspend |
291 | * @ctx_buf: common context memory (MFCv6) | ||
292 | * @warn_start: hardware error code from which warnings start | ||
293 | * @mfc_ops: ops structure holding HW operation function pointers | ||
294 | * @mfc_cmds: cmd structure holding HW commands function pointers | ||
215 | * | 295 | * |
216 | */ | 296 | */ |
217 | struct s5p_mfc_dev { | 297 | struct s5p_mfc_dev { |
@@ -226,6 +306,7 @@ struct s5p_mfc_dev { | |||
226 | struct v4l2_ctrl_handler dec_ctrl_handler; | 306 | struct v4l2_ctrl_handler dec_ctrl_handler; |
227 | struct v4l2_ctrl_handler enc_ctrl_handler; | 307 | struct v4l2_ctrl_handler enc_ctrl_handler; |
228 | struct s5p_mfc_pm pm; | 308 | struct s5p_mfc_pm pm; |
309 | struct s5p_mfc_variant *variant; | ||
229 | int num_inst; | 310 | int num_inst; |
230 | spinlock_t irqlock; /* lock when operating on videobuf2 queues */ | 311 | spinlock_t irqlock; /* lock when operating on videobuf2 queues */ |
231 | spinlock_t condlock; /* lock when changing/checking if a context is | 312 | spinlock_t condlock; /* lock when changing/checking if a context is |
@@ -248,6 +329,11 @@ struct s5p_mfc_dev { | |||
248 | struct work_struct watchdog_work; | 329 | struct work_struct watchdog_work; |
249 | void *alloc_ctx[2]; | 330 | void *alloc_ctx[2]; |
250 | unsigned long enter_suspend; | 331 | unsigned long enter_suspend; |
332 | |||
333 | struct s5p_mfc_priv_buf ctx_buf; | ||
334 | int warn_start; | ||
335 | struct s5p_mfc_hw_ops *mfc_ops; | ||
336 | struct s5p_mfc_hw_cmds *mfc_cmds; | ||
251 | }; | 337 | }; |
252 | 338 | ||
253 | /** | 339 | /** |
@@ -262,7 +348,6 @@ struct s5p_mfc_h264_enc_params { | |||
262 | u8 max_ref_pic; | 348 | u8 max_ref_pic; |
263 | u8 num_ref_pic_4p; | 349 | u8 num_ref_pic_4p; |
264 | int _8x8_transform; | 350 | int _8x8_transform; |
265 | int rc_mb; | ||
266 | int rc_mb_dark; | 351 | int rc_mb_dark; |
267 | int rc_mb_smooth; | 352 | int rc_mb_smooth; |
268 | int rc_mb_static; | 353 | int rc_mb_static; |
@@ -281,6 +366,23 @@ struct s5p_mfc_h264_enc_params { | |||
281 | enum v4l2_mpeg_video_h264_level level_v4l2; | 366 | enum v4l2_mpeg_video_h264_level level_v4l2; |
282 | int level; | 367 | int level; |
283 | u16 cpb_size; | 368 | u16 cpb_size; |
369 | int interlace; | ||
370 | u8 hier_qp; | ||
371 | u8 hier_qp_type; | ||
372 | u8 hier_qp_layer; | ||
373 | u8 hier_qp_layer_qp[7]; | ||
374 | u8 sei_frame_packing; | ||
375 | u8 sei_fp_curr_frame_0; | ||
376 | u8 sei_fp_arrangement_type; | ||
377 | |||
378 | u8 fmo; | ||
379 | u8 fmo_map_type; | ||
380 | u8 fmo_slice_grp; | ||
381 | u8 fmo_chg_dir; | ||
382 | u32 fmo_chg_rate; | ||
383 | u32 fmo_run_len[4]; | ||
384 | u8 aso; | ||
385 | u32 aso_slice_order[8]; | ||
284 | }; | 386 | }; |
285 | 387 | ||
286 | /** | 388 | /** |
@@ -319,9 +421,11 @@ struct s5p_mfc_enc_params { | |||
319 | u8 pad_cb; | 421 | u8 pad_cb; |
320 | u8 pad_cr; | 422 | u8 pad_cr; |
321 | int rc_frame; | 423 | int rc_frame; |
424 | int rc_mb; | ||
322 | u32 rc_bitrate; | 425 | u32 rc_bitrate; |
323 | u16 rc_reaction_coeff; | 426 | u16 rc_reaction_coeff; |
324 | u16 vbv_size; | 427 | u16 vbv_size; |
428 | u32 vbv_delay; | ||
325 | 429 | ||
326 | enum v4l2_mpeg_video_header_mode seq_hdr_mode; | 430 | enum v4l2_mpeg_video_header_mode seq_hdr_mode; |
327 | enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode; | 431 | enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode; |
@@ -330,7 +434,6 @@ struct s5p_mfc_enc_params { | |||
330 | u8 num_b_frame; | 434 | u8 num_b_frame; |
331 | u32 rc_framerate_num; | 435 | u32 rc_framerate_num; |
332 | u32 rc_framerate_denom; | 436 | u32 rc_framerate_denom; |
333 | int interlace; | ||
334 | 437 | ||
335 | union { | 438 | union { |
336 | struct s5p_mfc_h264_enc_params h264; | 439 | struct s5p_mfc_h264_enc_params h264; |
@@ -388,6 +491,8 @@ struct s5p_mfc_codec_ops { | |||
388 | * decoding buffer | 491 | * decoding buffer |
389 | * @dpb_flush_flag: flag used to indicate that a DPB buffers are being | 492 | * @dpb_flush_flag: flag used to indicate that a DPB buffers are being |
390 | * flushed | 493 | * flushed |
494 | * @head_processed: flag mentioning whether the header data is processed | ||
495 | * completely or not | ||
391 | * @bank1_buf: handle to memory allocated for temporary buffers from | 496 | * @bank1_buf: handle to memory allocated for temporary buffers from |
392 | * memory bank 1 | 497 | * memory bank 1 |
393 | * @bank1_phys: address of the temporary buffers from memory bank 1 | 498 | * @bank1_phys: address of the temporary buffers from memory bank 1 |
@@ -412,19 +517,20 @@ struct s5p_mfc_codec_ops { | |||
412 | * @display_delay_enable: display delay for H264 enable flag | 517 | * @display_delay_enable: display delay for H264 enable flag |
413 | * @after_packed_pb: flag used to track buffer when stream is in | 518 | * @after_packed_pb: flag used to track buffer when stream is in |
414 | * Packed PB format | 519 | * Packed PB format |
520 | * @sei_fp_parse: enable/disable parsing of frame packing SEI information | ||
415 | * @dpb_count: count of the DPB buffers required by MFC hw | 521 | * @dpb_count: count of the DPB buffers required by MFC hw |
416 | * @total_dpb_count: count of DPB buffers with additional buffers | 522 | * @total_dpb_count: count of DPB buffers with additional buffers |
417 | * requested by the application | 523 | * requested by the application |
418 | * @ctx_buf: handle to the memory associated with this context | 524 | * @ctx: context buffer information |
419 | * @ctx_phys: address of the memory associated with this context | 525 | * @dsc: descriptor buffer information |
420 | * @ctx_size: size of the memory associated with this context | 526 | * @shm: shared memory buffer information |
421 | * @desc_buf: description buffer for decoding handle | 527 | * @mv_count: number of MV buffers allocated for decoding |
422 | * @desc_phys: description buffer for decoding address | ||
423 | * @shm_alloc: handle for the shared memory buffer | ||
424 | * @shm: virtual address for the shared memory buffer | ||
425 | * @shm_ofs: address offset for shared memory | ||
426 | * @enc_params: encoding parameters for MFC | 528 | * @enc_params: encoding parameters for MFC |
427 | * @enc_dst_buf_size: size of the buffers for encoder output | 529 | * @enc_dst_buf_size: size of the buffers for encoder output |
530 | * @luma_dpb_size: dpb buffer size for luma | ||
531 | * @chroma_dpb_size: dpb buffer size for chroma | ||
532 | * @me_buffer_size: size of the motion estimation buffer | ||
533 | * @tmv_buffer_size: size of temporal predictor motion vector buffer | ||
428 | * @frame_type: used to force the type of the next encoded frame | 534 | * @frame_type: used to force the type of the next encoded frame |
429 | * @ref_queue: list of the reference buffers for encoding | 535 | * @ref_queue: list of the reference buffers for encoding |
430 | * @ref_queue_cnt: number of the buffers in the reference list | 536 | * @ref_queue_cnt: number of the buffers in the reference list |
@@ -473,6 +579,7 @@ struct s5p_mfc_ctx { | |||
473 | unsigned long consumed_stream; | 579 | unsigned long consumed_stream; |
474 | 580 | ||
475 | unsigned int dpb_flush_flag; | 581 | unsigned int dpb_flush_flag; |
582 | unsigned int head_processed; | ||
476 | 583 | ||
477 | /* Buffers */ | 584 | /* Buffers */ |
478 | void *bank1_buf; | 585 | void *bank1_buf; |
@@ -502,37 +609,41 @@ struct s5p_mfc_ctx { | |||
502 | int display_delay; | 609 | int display_delay; |
503 | int display_delay_enable; | 610 | int display_delay_enable; |
504 | int after_packed_pb; | 611 | int after_packed_pb; |
612 | int sei_fp_parse; | ||
505 | 613 | ||
506 | int dpb_count; | 614 | int dpb_count; |
507 | int total_dpb_count; | 615 | int total_dpb_count; |
508 | 616 | int mv_count; | |
509 | /* Buffers */ | 617 | /* Buffers */ |
510 | void *ctx_buf; | 618 | struct s5p_mfc_priv_buf ctx; |
511 | size_t ctx_phys; | 619 | struct s5p_mfc_priv_buf dsc; |
512 | size_t ctx_ofs; | 620 | struct s5p_mfc_priv_buf shm; |
513 | size_t ctx_size; | ||
514 | |||
515 | void *desc_buf; | ||
516 | size_t desc_phys; | ||
517 | |||
518 | |||
519 | void *shm_alloc; | ||
520 | void *shm; | ||
521 | size_t shm_ofs; | ||
522 | 621 | ||
523 | struct s5p_mfc_enc_params enc_params; | 622 | struct s5p_mfc_enc_params enc_params; |
524 | 623 | ||
525 | size_t enc_dst_buf_size; | 624 | size_t enc_dst_buf_size; |
625 | size_t luma_dpb_size; | ||
626 | size_t chroma_dpb_size; | ||
627 | size_t me_buffer_size; | ||
628 | size_t tmv_buffer_size; | ||
526 | 629 | ||
527 | enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type; | 630 | enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type; |
528 | 631 | ||
529 | struct list_head ref_queue; | 632 | struct list_head ref_queue; |
530 | unsigned int ref_queue_cnt; | 633 | unsigned int ref_queue_cnt; |
531 | 634 | ||
635 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; | ||
636 | union { | ||
637 | unsigned int mb; | ||
638 | unsigned int bits; | ||
639 | } slice_size; | ||
640 | |||
532 | struct s5p_mfc_codec_ops *c_ops; | 641 | struct s5p_mfc_codec_ops *c_ops; |
533 | 642 | ||
534 | struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS]; | 643 | struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS]; |
535 | struct v4l2_ctrl_handler ctrl_handler; | 644 | struct v4l2_ctrl_handler ctrl_handler; |
645 | unsigned int frame_tag; | ||
646 | size_t scratch_buf_size; | ||
536 | }; | 647 | }; |
537 | 648 | ||
538 | /* | 649 | /* |
@@ -565,6 +676,9 @@ struct mfc_control { | |||
565 | __u8 is_volatile; | 676 | __u8 is_volatile; |
566 | }; | 677 | }; |
567 | 678 | ||
679 | /* Macro for making hardware specific calls */ | ||
680 | #define s5p_mfc_hw_call(f, op, args...) \ | ||
681 | ((f && f->op) ? f->op(args) : -ENODEV) | ||
568 | 682 | ||
569 | #define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh) | 683 | #define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh) |
570 | #define ctrl_to_ctx(__ctrl) \ | 684 | #define ctrl_to_ctx(__ctrl) \ |
@@ -575,4 +689,9 @@ void set_work_bit(struct s5p_mfc_ctx *ctx); | |||
575 | void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx); | 689 | void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx); |
576 | void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); | 690 | void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); |
577 | 691 | ||
692 | #define HAS_PORTNUM(dev) (dev ? (dev->variant ? \ | ||
693 | (dev->variant->port_num ? 1 : 0) : 0) : 0) | ||
694 | #define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0) | ||
695 | #define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 : 0) | ||
696 | |||
578 | #endif /* S5P_MFC_COMMON_H_ */ | 697 | #endif /* S5P_MFC_COMMON_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 0deba6bc687c..585b7b0ed8ec 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | |||
@@ -15,11 +15,11 @@ | |||
15 | #include <linux/firmware.h> | 15 | #include <linux/firmware.h> |
16 | #include <linux/jiffies.h> | 16 | #include <linux/jiffies.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include "regs-mfc.h" | ||
19 | #include "s5p_mfc_cmd.h" | 18 | #include "s5p_mfc_cmd.h" |
20 | #include "s5p_mfc_common.h" | 19 | #include "s5p_mfc_common.h" |
21 | #include "s5p_mfc_debug.h" | 20 | #include "s5p_mfc_debug.h" |
22 | #include "s5p_mfc_intr.h" | 21 | #include "s5p_mfc_intr.h" |
22 | #include "s5p_mfc_opr.h" | ||
23 | #include "s5p_mfc_pm.h" | 23 | #include "s5p_mfc_pm.h" |
24 | 24 | ||
25 | static void *s5p_mfc_bitproc_buf; | 25 | static void *s5p_mfc_bitproc_buf; |
@@ -37,13 +37,19 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) | |||
37 | /* Firmare has to be present as a separate file or compiled | 37 | /* Firmare has to be present as a separate file or compiled |
38 | * into kernel. */ | 38 | * into kernel. */ |
39 | mfc_debug_enter(); | 39 | mfc_debug_enter(); |
40 | |||
40 | err = request_firmware((const struct firmware **)&fw_blob, | 41 | err = request_firmware((const struct firmware **)&fw_blob, |
41 | "s5p-mfc.fw", dev->v4l2_dev.dev); | 42 | dev->variant->fw_name, dev->v4l2_dev.dev); |
42 | if (err != 0) { | 43 | if (err != 0) { |
43 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); | 44 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); |
44 | return -EINVAL; | 45 | return -EINVAL; |
45 | } | 46 | } |
46 | dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN); | 47 | dev->fw_size = dev->variant->buf_size->fw; |
48 | if (fw_blob->size > dev->fw_size) { | ||
49 | mfc_err("MFC firmware is too big to be loaded\n"); | ||
50 | release_firmware(fw_blob); | ||
51 | return -ENOMEM; | ||
52 | } | ||
47 | if (s5p_mfc_bitproc_buf) { | 53 | if (s5p_mfc_bitproc_buf) { |
48 | mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); | 54 | mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); |
49 | release_firmware(fw_blob); | 55 | release_firmware(fw_blob); |
@@ -77,32 +83,37 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) | |||
77 | return -EIO; | 83 | return -EIO; |
78 | } | 84 | } |
79 | dev->bank1 = s5p_mfc_bitproc_phys; | 85 | dev->bank1 = s5p_mfc_bitproc_phys; |
80 | b_base = vb2_dma_contig_memops.alloc( | 86 | if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { |
81 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER); | 87 | b_base = vb2_dma_contig_memops.alloc( |
82 | if (IS_ERR(b_base)) { | 88 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], |
83 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | 89 | 1 << MFC_BASE_ALIGN_ORDER); |
84 | s5p_mfc_bitproc_phys = 0; | 90 | if (IS_ERR(b_base)) { |
85 | s5p_mfc_bitproc_buf = NULL; | 91 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); |
86 | mfc_err("Allocating bank2 base failed\n"); | 92 | s5p_mfc_bitproc_phys = 0; |
87 | release_firmware(fw_blob); | 93 | s5p_mfc_bitproc_buf = NULL; |
88 | return -ENOMEM; | 94 | mfc_err("Allocating bank2 base failed\n"); |
89 | } | 95 | release_firmware(fw_blob); |
90 | bank2_base_phys = s5p_mfc_mem_cookie( | 96 | return -ENOMEM; |
91 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base); | 97 | } |
92 | vb2_dma_contig_memops.put(b_base); | 98 | bank2_base_phys = s5p_mfc_mem_cookie( |
93 | if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) { | 99 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base); |
94 | mfc_err("The base memory for bank 2 is not aligned to 128KB\n"); | 100 | vb2_dma_contig_memops.put(b_base); |
95 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); | 101 | if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) { |
96 | s5p_mfc_bitproc_phys = 0; | 102 | mfc_err("The base memory for bank 2 is not aligned to 128KB\n"); |
97 | s5p_mfc_bitproc_buf = NULL; | 103 | vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); |
98 | release_firmware(fw_blob); | 104 | s5p_mfc_bitproc_phys = 0; |
99 | return -EIO; | 105 | s5p_mfc_bitproc_buf = NULL; |
106 | release_firmware(fw_blob); | ||
107 | return -EIO; | ||
108 | } | ||
109 | /* Valid buffers passed to MFC encoder with LAST_FRAME command | ||
110 | * should not have address of bank2 - MFC will treat it as a null frame. | ||
111 | * To avoid such situation we set bank2 address below the pool address. | ||
112 | */ | ||
113 | dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER); | ||
114 | } else { | ||
115 | dev->bank2 = dev->bank1; | ||
100 | } | 116 | } |
101 | /* Valid buffers passed to MFC encoder with LAST_FRAME command | ||
102 | * should not have address of bank2 - MFC will treat it as a null frame. | ||
103 | * To avoid such situation we set bank2 address below the pool address. | ||
104 | */ | ||
105 | dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER); | ||
106 | memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); | 117 | memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); |
107 | wmb(); | 118 | wmb(); |
108 | release_firmware(fw_blob); | 119 | release_firmware(fw_blob); |
@@ -119,8 +130,9 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev) | |||
119 | /* Firmare has to be present as a separate file or compiled | 130 | /* Firmare has to be present as a separate file or compiled |
120 | * into kernel. */ | 131 | * into kernel. */ |
121 | mfc_debug_enter(); | 132 | mfc_debug_enter(); |
133 | |||
122 | err = request_firmware((const struct firmware **)&fw_blob, | 134 | err = request_firmware((const struct firmware **)&fw_blob, |
123 | "s5p-mfc.fw", dev->v4l2_dev.dev); | 135 | dev->variant->fw_name, dev->v4l2_dev.dev); |
124 | if (err != 0) { | 136 | if (err != 0) { |
125 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); | 137 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); |
126 | return -EINVAL; | 138 | return -EINVAL; |
@@ -161,46 +173,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) | |||
161 | { | 173 | { |
162 | unsigned int mc_status; | 174 | unsigned int mc_status; |
163 | unsigned long timeout; | 175 | unsigned long timeout; |
176 | int i; | ||
164 | 177 | ||
165 | mfc_debug_enter(); | 178 | mfc_debug_enter(); |
166 | /* Stop procedure */ | ||
167 | /* reset RISC */ | ||
168 | mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET); | ||
169 | /* All reset except for MC */ | ||
170 | mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET); | ||
171 | mdelay(10); | ||
172 | |||
173 | timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); | ||
174 | /* Check MC status */ | ||
175 | do { | ||
176 | if (time_after(jiffies, timeout)) { | ||
177 | mfc_err("Timeout while resetting MFC\n"); | ||
178 | return -EIO; | ||
179 | } | ||
180 | 179 | ||
181 | mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS); | 180 | if (IS_MFCV6(dev)) { |
181 | /* Reset IP */ | ||
182 | /* except RISC, reset */ | ||
183 | mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6); | ||
184 | /* reset release */ | ||
185 | mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6); | ||
186 | |||
187 | /* Zero Initialization of MFC registers */ | ||
188 | mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6); | ||
189 | mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6); | ||
190 | mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6); | ||
191 | |||
192 | for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++) | ||
193 | mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4)); | ||
182 | 194 | ||
183 | } while (mc_status & 0x3); | 195 | /* Reset */ |
196 | mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6); | ||
197 | mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6); | ||
198 | mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6); | ||
199 | } else { | ||
200 | /* Stop procedure */ | ||
201 | /* reset RISC */ | ||
202 | mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET); | ||
203 | /* All reset except for MC */ | ||
204 | mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET); | ||
205 | mdelay(10); | ||
206 | |||
207 | timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); | ||
208 | /* Check MC status */ | ||
209 | do { | ||
210 | if (time_after(jiffies, timeout)) { | ||
211 | mfc_err("Timeout while resetting MFC\n"); | ||
212 | return -EIO; | ||
213 | } | ||
214 | |||
215 | mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS); | ||
216 | |||
217 | } while (mc_status & 0x3); | ||
218 | |||
219 | mfc_write(dev, 0x0, S5P_FIMV_SW_RESET); | ||
220 | mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET); | ||
221 | } | ||
184 | 222 | ||
185 | mfc_write(dev, 0x0, S5P_FIMV_SW_RESET); | ||
186 | mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET); | ||
187 | mfc_debug_leave(); | 223 | mfc_debug_leave(); |
188 | return 0; | 224 | return 0; |
189 | } | 225 | } |
190 | 226 | ||
191 | static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) | 227 | static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) |
192 | { | 228 | { |
193 | mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A); | 229 | if (IS_MFCV6(dev)) { |
194 | mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B); | 230 | mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); |
195 | mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2); | 231 | mfc_debug(2, "Base Address : %08x\n", dev->bank1); |
232 | } else { | ||
233 | mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A); | ||
234 | mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B); | ||
235 | mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", | ||
236 | dev->bank1, dev->bank2); | ||
237 | } | ||
196 | } | 238 | } |
197 | 239 | ||
198 | static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) | 240 | static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) |
199 | { | 241 | { |
200 | mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID); | 242 | if (IS_MFCV6(dev)) { |
201 | mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID); | 243 | /* Zero initialization should be done before RESET. |
202 | mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD); | 244 | * Nothing to do here. */ |
203 | mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD); | 245 | } else { |
246 | mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID); | ||
247 | mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID); | ||
248 | mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD); | ||
249 | mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD); | ||
250 | } | ||
204 | } | 251 | } |
205 | 252 | ||
206 | /* Initialize hardware */ | 253 | /* Initialize hardware */ |
@@ -228,9 +275,12 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
228 | s5p_mfc_clear_cmds(dev); | 275 | s5p_mfc_clear_cmds(dev); |
229 | /* 3. Release reset signal to the RISC */ | 276 | /* 3. Release reset signal to the RISC */ |
230 | s5p_mfc_clean_dev_int_flags(dev); | 277 | s5p_mfc_clean_dev_int_flags(dev); |
231 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | 278 | if (IS_MFCV6(dev)) |
279 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); | ||
280 | else | ||
281 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | ||
232 | mfc_debug(2, "Will now wait for completion of firmware transfer\n"); | 282 | mfc_debug(2, "Will now wait for completion of firmware transfer\n"); |
233 | if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) { | 283 | if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) { |
234 | mfc_err("Failed to load firmware\n"); | 284 | mfc_err("Failed to load firmware\n"); |
235 | s5p_mfc_reset(dev); | 285 | s5p_mfc_reset(dev); |
236 | s5p_mfc_clock_off(); | 286 | s5p_mfc_clock_off(); |
@@ -238,7 +288,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
238 | } | 288 | } |
239 | s5p_mfc_clean_dev_int_flags(dev); | 289 | s5p_mfc_clean_dev_int_flags(dev); |
240 | /* 4. Initialize firmware */ | 290 | /* 4. Initialize firmware */ |
241 | ret = s5p_mfc_sys_init_cmd(dev); | 291 | ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev); |
242 | if (ret) { | 292 | if (ret) { |
243 | mfc_err("Failed to send command to MFC - timeout\n"); | 293 | mfc_err("Failed to send command to MFC - timeout\n"); |
244 | s5p_mfc_reset(dev); | 294 | s5p_mfc_reset(dev); |
@@ -246,7 +296,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
246 | return ret; | 296 | return ret; |
247 | } | 297 | } |
248 | mfc_debug(2, "Ok, now will write a command to init the system\n"); | 298 | mfc_debug(2, "Ok, now will write a command to init the system\n"); |
249 | if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) { | 299 | if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) { |
250 | mfc_err("Failed to load firmware\n"); | 300 | mfc_err("Failed to load firmware\n"); |
251 | s5p_mfc_reset(dev); | 301 | s5p_mfc_reset(dev); |
252 | s5p_mfc_clock_off(); | 302 | s5p_mfc_clock_off(); |
@@ -254,7 +304,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
254 | } | 304 | } |
255 | dev->int_cond = 0; | 305 | dev->int_cond = 0; |
256 | if (dev->int_err != 0 || dev->int_type != | 306 | if (dev->int_err != 0 || dev->int_type != |
257 | S5P_FIMV_R2H_CMD_SYS_INIT_RET) { | 307 | S5P_MFC_R2H_CMD_SYS_INIT_RET) { |
258 | /* Failure. */ | 308 | /* Failure. */ |
259 | mfc_err("Failed to init firmware - error: %d int: %d\n", | 309 | mfc_err("Failed to init firmware - error: %d int: %d\n", |
260 | dev->int_err, dev->int_type); | 310 | dev->int_err, dev->int_type); |
@@ -262,7 +312,11 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
262 | s5p_mfc_clock_off(); | 312 | s5p_mfc_clock_off(); |
263 | return -EIO; | 313 | return -EIO; |
264 | } | 314 | } |
265 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION); | 315 | if (IS_MFCV6(dev)) |
316 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); | ||
317 | else | ||
318 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION); | ||
319 | |||
266 | mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n", | 320 | mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n", |
267 | (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF); | 321 | (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF); |
268 | s5p_mfc_clock_off(); | 322 | s5p_mfc_clock_off(); |
@@ -271,6 +325,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
271 | } | 325 | } |
272 | 326 | ||
273 | 327 | ||
328 | /* Deinitialize hardware */ | ||
329 | void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev) | ||
330 | { | ||
331 | s5p_mfc_clock_on(); | ||
332 | |||
333 | s5p_mfc_reset(dev); | ||
334 | s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev); | ||
335 | |||
336 | s5p_mfc_clock_off(); | ||
337 | } | ||
338 | |||
274 | int s5p_mfc_sleep(struct s5p_mfc_dev *dev) | 339 | int s5p_mfc_sleep(struct s5p_mfc_dev *dev) |
275 | { | 340 | { |
276 | int ret; | 341 | int ret; |
@@ -278,19 +343,19 @@ int s5p_mfc_sleep(struct s5p_mfc_dev *dev) | |||
278 | mfc_debug_enter(); | 343 | mfc_debug_enter(); |
279 | s5p_mfc_clock_on(); | 344 | s5p_mfc_clock_on(); |
280 | s5p_mfc_clean_dev_int_flags(dev); | 345 | s5p_mfc_clean_dev_int_flags(dev); |
281 | ret = s5p_mfc_sleep_cmd(dev); | 346 | ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev); |
282 | if (ret) { | 347 | if (ret) { |
283 | mfc_err("Failed to send command to MFC - timeout\n"); | 348 | mfc_err("Failed to send command to MFC - timeout\n"); |
284 | return ret; | 349 | return ret; |
285 | } | 350 | } |
286 | if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) { | 351 | if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) { |
287 | mfc_err("Failed to sleep\n"); | 352 | mfc_err("Failed to sleep\n"); |
288 | return -EIO; | 353 | return -EIO; |
289 | } | 354 | } |
290 | s5p_mfc_clock_off(); | 355 | s5p_mfc_clock_off(); |
291 | dev->int_cond = 0; | 356 | dev->int_cond = 0; |
292 | if (dev->int_err != 0 || dev->int_type != | 357 | if (dev->int_err != 0 || dev->int_type != |
293 | S5P_FIMV_R2H_CMD_SLEEP_RET) { | 358 | S5P_MFC_R2H_CMD_SLEEP_RET) { |
294 | /* Failure. */ | 359 | /* Failure. */ |
295 | mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err, | 360 | mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err, |
296 | dev->int_type); | 361 | dev->int_type); |
@@ -320,22 +385,25 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) | |||
320 | s5p_mfc_clear_cmds(dev); | 385 | s5p_mfc_clear_cmds(dev); |
321 | s5p_mfc_clean_dev_int_flags(dev); | 386 | s5p_mfc_clean_dev_int_flags(dev); |
322 | /* 3. Initialize firmware */ | 387 | /* 3. Initialize firmware */ |
323 | ret = s5p_mfc_wakeup_cmd(dev); | 388 | ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev); |
324 | if (ret) { | 389 | if (ret) { |
325 | mfc_err("Failed to send command to MFC - timeout\n"); | 390 | mfc_err("Failed to send command to MFC - timeout\n"); |
326 | return ret; | 391 | return ret; |
327 | } | 392 | } |
328 | /* 4. Release reset signal to the RISC */ | 393 | /* 4. Release reset signal to the RISC */ |
329 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | 394 | if (IS_MFCV6(dev)) |
395 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); | ||
396 | else | ||
397 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | ||
330 | mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); | 398 | mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); |
331 | if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) { | 399 | if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) { |
332 | mfc_err("Failed to load firmware\n"); | 400 | mfc_err("Failed to load firmware\n"); |
333 | return -EIO; | 401 | return -EIO; |
334 | } | 402 | } |
335 | s5p_mfc_clock_off(); | 403 | s5p_mfc_clock_off(); |
336 | dev->int_cond = 0; | 404 | dev->int_cond = 0; |
337 | if (dev->int_err != 0 || dev->int_type != | 405 | if (dev->int_err != 0 || dev->int_type != |
338 | S5P_FIMV_R2H_CMD_WAKEUP_RET) { | 406 | S5P_MFC_R2H_CMD_WAKEUP_RET) { |
339 | /* Failure. */ | 407 | /* Failure. */ |
340 | mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err, | 408 | mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err, |
341 | dev->int_type); | 409 | dev->int_type); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h index e1e0c544b6a2..90aa9b9886d5 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | |||
@@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev); | |||
20 | int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); | 20 | int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); |
21 | 21 | ||
22 | int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); | 22 | int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); |
23 | void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev); | ||
23 | 24 | ||
24 | int s5p_mfc_sleep(struct s5p_mfc_dev *dev); | 25 | int s5p_mfc_sleep(struct s5p_mfc_dev *dev); |
25 | int s5p_mfc_wakeup(struct s5p_mfc_dev *dev); | 26 | int s5p_mfc_wakeup(struct s5p_mfc_dev *dev); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 6ee21bb71398..eb6a70b0f821 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
@@ -23,85 +23,114 @@ | |||
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <media/v4l2-ctrls.h> | 24 | #include <media/v4l2-ctrls.h> |
25 | #include <media/videobuf2-core.h> | 25 | #include <media/videobuf2-core.h> |
26 | #include "regs-mfc.h" | ||
27 | #include "s5p_mfc_common.h" | 26 | #include "s5p_mfc_common.h" |
28 | #include "s5p_mfc_debug.h" | 27 | #include "s5p_mfc_debug.h" |
29 | #include "s5p_mfc_dec.h" | 28 | #include "s5p_mfc_dec.h" |
30 | #include "s5p_mfc_intr.h" | 29 | #include "s5p_mfc_intr.h" |
31 | #include "s5p_mfc_opr.h" | 30 | #include "s5p_mfc_opr.h" |
32 | #include "s5p_mfc_pm.h" | 31 | #include "s5p_mfc_pm.h" |
33 | #include "s5p_mfc_shm.h" | 32 | |
33 | #define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264 | ||
34 | #define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT_16X16 | ||
34 | 35 | ||
35 | static struct s5p_mfc_fmt formats[] = { | 36 | static struct s5p_mfc_fmt formats[] = { |
36 | { | 37 | { |
38 | .name = "4:2:0 2 Planes 16x16 Tiles", | ||
39 | .fourcc = V4L2_PIX_FMT_NV12MT_16X16, | ||
40 | .codec_mode = S5P_MFC_CODEC_NONE, | ||
41 | .type = MFC_FMT_RAW, | ||
42 | .num_planes = 2, | ||
43 | }, | ||
44 | { | ||
37 | .name = "4:2:0 2 Planes 64x32 Tiles", | 45 | .name = "4:2:0 2 Planes 64x32 Tiles", |
38 | .fourcc = V4L2_PIX_FMT_NV12MT, | 46 | .fourcc = V4L2_PIX_FMT_NV12MT, |
39 | .codec_mode = S5P_FIMV_CODEC_NONE, | 47 | .codec_mode = S5P_MFC_CODEC_NONE, |
40 | .type = MFC_FMT_RAW, | 48 | .type = MFC_FMT_RAW, |
41 | .num_planes = 2, | 49 | .num_planes = 2, |
42 | }, | 50 | }, |
43 | { | 51 | { |
44 | .name = "4:2:0 2 Planes", | 52 | .name = "4:2:0 2 Planes Y/CbCr", |
45 | .fourcc = V4L2_PIX_FMT_NV12M, | 53 | .fourcc = V4L2_PIX_FMT_NV12M, |
46 | .codec_mode = S5P_FIMV_CODEC_NONE, | 54 | .codec_mode = S5P_MFC_CODEC_NONE, |
47 | .type = MFC_FMT_RAW, | 55 | .type = MFC_FMT_RAW, |
48 | .num_planes = 2, | 56 | .num_planes = 2, |
57 | }, | ||
58 | { | ||
59 | .name = "4:2:0 2 Planes Y/CrCb", | ||
60 | .fourcc = V4L2_PIX_FMT_NV21M, | ||
61 | .codec_mode = S5P_MFC_CODEC_NONE, | ||
62 | .type = MFC_FMT_RAW, | ||
63 | .num_planes = 2, | ||
49 | }, | 64 | }, |
50 | { | 65 | { |
51 | .name = "H264 Encoded Stream", | 66 | .name = "H264 Encoded Stream", |
52 | .fourcc = V4L2_PIX_FMT_H264, | 67 | .fourcc = V4L2_PIX_FMT_H264, |
53 | .codec_mode = S5P_FIMV_CODEC_H264_DEC, | 68 | .codec_mode = S5P_MFC_CODEC_H264_DEC, |
54 | .type = MFC_FMT_DEC, | 69 | .type = MFC_FMT_DEC, |
55 | .num_planes = 1, | 70 | .num_planes = 1, |
56 | }, | 71 | }, |
57 | { | 72 | { |
58 | .name = "H263 Encoded Stream", | 73 | .name = "H264/MVC Encoded Stream", |
59 | .fourcc = V4L2_PIX_FMT_H263, | 74 | .fourcc = V4L2_PIX_FMT_H264_MVC, |
60 | .codec_mode = S5P_FIMV_CODEC_H263_DEC, | 75 | .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC, |
61 | .type = MFC_FMT_DEC, | 76 | .type = MFC_FMT_DEC, |
62 | .num_planes = 1, | 77 | .num_planes = 1, |
63 | }, | 78 | }, |
64 | { | 79 | { |
65 | .name = "MPEG1 Encoded Stream", | 80 | .name = "H263 Encoded Stream", |
66 | .fourcc = V4L2_PIX_FMT_MPEG1, | 81 | .fourcc = V4L2_PIX_FMT_H263, |
67 | .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC, | 82 | .codec_mode = S5P_MFC_CODEC_H263_DEC, |
68 | .type = MFC_FMT_DEC, | 83 | .type = MFC_FMT_DEC, |
69 | .num_planes = 1, | 84 | .num_planes = 1, |
70 | }, | 85 | }, |
71 | { | 86 | { |
72 | .name = "MPEG2 Encoded Stream", | 87 | .name = "MPEG1 Encoded Stream", |
73 | .fourcc = V4L2_PIX_FMT_MPEG2, | 88 | .fourcc = V4L2_PIX_FMT_MPEG1, |
74 | .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC, | 89 | .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, |
75 | .type = MFC_FMT_DEC, | 90 | .type = MFC_FMT_DEC, |
76 | .num_planes = 1, | 91 | .num_planes = 1, |
77 | }, | 92 | }, |
78 | { | 93 | { |
79 | .name = "MPEG4 Encoded Stream", | 94 | .name = "MPEG2 Encoded Stream", |
80 | .fourcc = V4L2_PIX_FMT_MPEG4, | 95 | .fourcc = V4L2_PIX_FMT_MPEG2, |
81 | .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC, | 96 | .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, |
82 | .type = MFC_FMT_DEC, | 97 | .type = MFC_FMT_DEC, |
83 | .num_planes = 1, | 98 | .num_planes = 1, |
84 | }, | 99 | }, |
85 | { | 100 | { |
86 | .name = "XviD Encoded Stream", | 101 | .name = "MPEG4 Encoded Stream", |
87 | .fourcc = V4L2_PIX_FMT_XVID, | 102 | .fourcc = V4L2_PIX_FMT_MPEG4, |
88 | .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC, | 103 | .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, |
89 | .type = MFC_FMT_DEC, | 104 | .type = MFC_FMT_DEC, |
90 | .num_planes = 1, | 105 | .num_planes = 1, |
91 | }, | 106 | }, |
92 | { | 107 | { |
93 | .name = "VC1 Encoded Stream", | 108 | .name = "XviD Encoded Stream", |
94 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G, | 109 | .fourcc = V4L2_PIX_FMT_XVID, |
95 | .codec_mode = S5P_FIMV_CODEC_VC1_DEC, | 110 | .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, |
96 | .type = MFC_FMT_DEC, | 111 | .type = MFC_FMT_DEC, |
97 | .num_planes = 1, | 112 | .num_planes = 1, |
98 | }, | 113 | }, |
99 | { | 114 | { |
100 | .name = "VC1 RCV Encoded Stream", | 115 | .name = "VC1 Encoded Stream", |
101 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L, | 116 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G, |
102 | .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC, | 117 | .codec_mode = S5P_MFC_CODEC_VC1_DEC, |
103 | .type = MFC_FMT_DEC, | 118 | .type = MFC_FMT_DEC, |
104 | .num_planes = 1, | 119 | .num_planes = 1, |
120 | }, | ||
121 | { | ||
122 | .name = "VC1 RCV Encoded Stream", | ||
123 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L, | ||
124 | .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC, | ||
125 | .type = MFC_FMT_DEC, | ||
126 | .num_planes = 1, | ||
127 | }, | ||
128 | { | ||
129 | .name = "VP8 Encoded Stream", | ||
130 | .fourcc = V4L2_PIX_FMT_VP8, | ||
131 | .codec_mode = S5P_MFC_CODEC_VP8_DEC, | ||
132 | .type = MFC_FMT_DEC, | ||
133 | .num_planes = 1, | ||
105 | }, | 134 | }, |
106 | }; | 135 | }; |
107 | 136 | ||
@@ -297,7 +326,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
297 | /* If the MFC is parsing the header, | 326 | /* If the MFC is parsing the header, |
298 | * so wait until it is finished */ | 327 | * so wait until it is finished */ |
299 | s5p_mfc_clean_ctx_int_flags(ctx); | 328 | s5p_mfc_clean_ctx_int_flags(ctx); |
300 | s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET, | 329 | s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET, |
301 | 0); | 330 | 0); |
302 | } | 331 | } |
303 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | 332 | 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) | |||
342 | /* Try format */ | 371 | /* Try format */ |
343 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | 372 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) |
344 | { | 373 | { |
374 | struct s5p_mfc_dev *dev = video_drvdata(file); | ||
345 | struct s5p_mfc_fmt *fmt; | 375 | struct s5p_mfc_fmt *fmt; |
346 | 376 | ||
347 | if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 377 | mfc_debug(2, "Type is %d\n", f->type); |
348 | mfc_err("This node supports decoding only\n"); | 378 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
349 | return -EINVAL; | 379 | fmt = find_format(f, MFC_FMT_DEC); |
350 | } | 380 | if (!fmt) { |
351 | fmt = find_format(f, MFC_FMT_DEC); | 381 | mfc_err("Unsupported format for source.\n"); |
352 | if (!fmt) { | 382 | return -EINVAL; |
353 | mfc_err("Unsupported format\n"); | 383 | } |
354 | return -EINVAL; | 384 | if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { |
355 | } | 385 | mfc_err("Not supported format.\n"); |
356 | if (fmt->type != MFC_FMT_DEC) { | 386 | return -EINVAL; |
357 | mfc_err("\n"); | 387 | } |
358 | return -EINVAL; | 388 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
389 | fmt = find_format(f, MFC_FMT_RAW); | ||
390 | if (!fmt) { | ||
391 | mfc_err("Unsupported format for destination.\n"); | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
395 | mfc_err("Not supported format.\n"); | ||
396 | return -EINVAL; | ||
397 | } else if (!IS_MFCV6(dev) && | ||
398 | (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { | ||
399 | mfc_err("Not supported format.\n"); | ||
400 | return -EINVAL; | ||
401 | } | ||
359 | } | 402 | } |
403 | |||
360 | return 0; | 404 | return 0; |
361 | } | 405 | } |
362 | 406 | ||
@@ -379,8 +423,29 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
379 | ret = -EBUSY; | 423 | ret = -EBUSY; |
380 | goto out; | 424 | goto out; |
381 | } | 425 | } |
426 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
427 | fmt = find_format(f, MFC_FMT_RAW); | ||
428 | if (!fmt) { | ||
429 | mfc_err("Unsupported format for source.\n"); | ||
430 | return -EINVAL; | ||
431 | } | ||
432 | if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { | ||
433 | mfc_err("Not supported format.\n"); | ||
434 | return -EINVAL; | ||
435 | } else if (IS_MFCV6(dev) && | ||
436 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
437 | mfc_err("Not supported format.\n"); | ||
438 | return -EINVAL; | ||
439 | } | ||
440 | ctx->dst_fmt = fmt; | ||
441 | mfc_debug_leave(); | ||
442 | return ret; | ||
443 | } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
444 | mfc_err("Wrong type error for S_FMT : %d", f->type); | ||
445 | return -EINVAL; | ||
446 | } | ||
382 | fmt = find_format(f, MFC_FMT_DEC); | 447 | fmt = find_format(f, MFC_FMT_DEC); |
383 | if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) { | 448 | if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) { |
384 | mfc_err("Unknown codec\n"); | 449 | mfc_err("Unknown codec\n"); |
385 | ret = -EINVAL; | 450 | ret = -EINVAL; |
386 | goto out; | 451 | goto out; |
@@ -391,6 +456,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
391 | ret = -EINVAL; | 456 | ret = -EINVAL; |
392 | goto out; | 457 | goto out; |
393 | } | 458 | } |
459 | if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { | ||
460 | mfc_err("Not supported format.\n"); | ||
461 | return -EINVAL; | ||
462 | } | ||
394 | ctx->src_fmt = fmt; | 463 | ctx->src_fmt = fmt; |
395 | ctx->codec_mode = fmt->codec_mode; | 464 | ctx->codec_mode = fmt->codec_mode; |
396 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | 465 | 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, | |||
476 | return -ENOMEM; | 545 | return -ENOMEM; |
477 | } | 546 | } |
478 | ctx->total_dpb_count = reqbufs->count; | 547 | ctx->total_dpb_count = reqbufs->count; |
479 | ret = s5p_mfc_alloc_codec_buffers(ctx); | 548 | ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); |
480 | if (ret) { | 549 | if (ret) { |
481 | mfc_err("Failed to allocate decoding buffers\n"); | 550 | mfc_err("Failed to allocate decoding buffers\n"); |
482 | reqbufs->count = 0; | 551 | reqbufs->count = 0; |
@@ -492,15 +561,16 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
492 | reqbufs->count = 0; | 561 | reqbufs->count = 0; |
493 | s5p_mfc_clock_on(); | 562 | s5p_mfc_clock_on(); |
494 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | 563 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); |
495 | s5p_mfc_release_codec_buffers(ctx); | 564 | s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, |
565 | ctx); | ||
496 | s5p_mfc_clock_off(); | 566 | s5p_mfc_clock_off(); |
497 | return -ENOMEM; | 567 | return -ENOMEM; |
498 | } | 568 | } |
499 | if (s5p_mfc_ctx_ready(ctx)) | 569 | if (s5p_mfc_ctx_ready(ctx)) |
500 | set_work_bit_irqsave(ctx); | 570 | set_work_bit_irqsave(ctx); |
501 | s5p_mfc_try_run(dev); | 571 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
502 | s5p_mfc_wait_for_done_ctx(ctx, | 572 | s5p_mfc_wait_for_done_ctx(ctx, |
503 | S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0); | 573 | S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); |
504 | } | 574 | } |
505 | return ret; | 575 | return ret; |
506 | } | 576 | } |
@@ -582,18 +652,22 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
582 | ctx->src_bufs_cnt = 0; | 652 | ctx->src_bufs_cnt = 0; |
583 | ctx->capture_state = QUEUE_FREE; | 653 | ctx->capture_state = QUEUE_FREE; |
584 | ctx->output_state = QUEUE_FREE; | 654 | ctx->output_state = QUEUE_FREE; |
585 | s5p_mfc_alloc_instance_buffer(ctx); | 655 | s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, |
586 | s5p_mfc_alloc_dec_temp_buffers(ctx); | 656 | ctx); |
657 | s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers, | ||
658 | ctx); | ||
587 | set_work_bit_irqsave(ctx); | 659 | set_work_bit_irqsave(ctx); |
588 | s5p_mfc_clean_ctx_int_flags(ctx); | 660 | s5p_mfc_clean_ctx_int_flags(ctx); |
589 | s5p_mfc_try_run(dev); | 661 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
590 | 662 | ||
591 | if (s5p_mfc_wait_for_done_ctx(ctx, | 663 | if (s5p_mfc_wait_for_done_ctx(ctx, |
592 | S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) { | 664 | S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { |
593 | /* Error or timeout */ | 665 | /* Error or timeout */ |
594 | mfc_err("Error getting instance from hardware\n"); | 666 | mfc_err("Error getting instance from hardware\n"); |
595 | s5p_mfc_release_instance_buffer(ctx); | 667 | s5p_mfc_hw_call(dev->mfc_ops, |
596 | s5p_mfc_release_dec_desc_buffer(ctx); | 668 | release_instance_buffer, ctx); |
669 | s5p_mfc_hw_call(dev->mfc_ops, | ||
670 | release_dec_desc_buffer, ctx); | ||
597 | return -EIO; | 671 | return -EIO; |
598 | } | 672 | } |
599 | mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); | 673 | 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) | |||
662 | /* Should wait for the header to be parsed */ | 736 | /* Should wait for the header to be parsed */ |
663 | s5p_mfc_clean_ctx_int_flags(ctx); | 737 | s5p_mfc_clean_ctx_int_flags(ctx); |
664 | s5p_mfc_wait_for_done_ctx(ctx, | 738 | s5p_mfc_wait_for_done_ctx(ctx, |
665 | S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0); | 739 | S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); |
666 | if (ctx->state >= MFCINST_HEAD_PARSED && | 740 | if (ctx->state >= MFCINST_HEAD_PARSED && |
667 | ctx->state < MFCINST_ABORT) { | 741 | ctx->state < MFCINST_ABORT) { |
668 | ctrl->val = ctx->dpb_count; | 742 | ctrl->val = ctx->dpb_count; |
@@ -686,6 +760,7 @@ static int vidioc_g_crop(struct file *file, void *priv, | |||
686 | struct v4l2_crop *cr) | 760 | struct v4l2_crop *cr) |
687 | { | 761 | { |
688 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | 762 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
763 | struct s5p_mfc_dev *dev = ctx->dev; | ||
689 | u32 left, right, top, bottom; | 764 | u32 left, right, top, bottom; |
690 | 765 | ||
691 | if (ctx->state != MFCINST_HEAD_PARSED && | 766 | if (ctx->state != MFCINST_HEAD_PARSED && |
@@ -695,10 +770,10 @@ static int vidioc_g_crop(struct file *file, void *priv, | |||
695 | return -EINVAL; | 770 | return -EINVAL; |
696 | } | 771 | } |
697 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) { | 772 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) { |
698 | left = s5p_mfc_read_shm(ctx, CROP_INFO_H); | 773 | left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx); |
699 | right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT; | 774 | right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT; |
700 | left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK; | 775 | left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK; |
701 | top = s5p_mfc_read_shm(ctx, CROP_INFO_V); | 776 | top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx); |
702 | bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT; | 777 | bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT; |
703 | top = top & S5P_FIMV_SHARED_CROP_TOP_MASK; | 778 | top = top & S5P_FIMV_SHARED_CROP_TOP_MASK; |
704 | cr->c.left = left; | 779 | cr->c.left = left; |
@@ -749,6 +824,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
749 | void *allocators[]) | 824 | void *allocators[]) |
750 | { | 825 | { |
751 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | 826 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); |
827 | struct s5p_mfc_dev *dev = ctx->dev; | ||
752 | 828 | ||
753 | /* Video output for decoding (source) | 829 | /* Video output for decoding (source) |
754 | * this can be set after getting an instance */ | 830 | * this can be set after getting an instance */ |
@@ -784,7 +860,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
784 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 860 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
785 | psize[0] = ctx->luma_size; | 861 | psize[0] = ctx->luma_size; |
786 | psize[1] = ctx->chroma_size; | 862 | psize[1] = ctx->chroma_size; |
787 | allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | 863 | |
864 | if (IS_MFCV6(dev)) | ||
865 | allocators[0] = | ||
866 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | ||
867 | else | ||
868 | allocators[0] = | ||
869 | ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | ||
788 | allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | 870 | allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; |
789 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && | 871 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && |
790 | ctx->state == MFCINST_INIT) { | 872 | ctx->state == MFCINST_INIT) { |
@@ -876,7 +958,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) | |||
876 | /* If context is ready then dev = work->data;schedule it to run */ | 958 | /* If context is ready then dev = work->data;schedule it to run */ |
877 | if (s5p_mfc_ctx_ready(ctx)) | 959 | if (s5p_mfc_ctx_ready(ctx)) |
878 | set_work_bit_irqsave(ctx); | 960 | set_work_bit_irqsave(ctx); |
879 | s5p_mfc_try_run(dev); | 961 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
880 | return 0; | 962 | return 0; |
881 | } | 963 | } |
882 | 964 | ||
@@ -892,19 +974,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |||
892 | dev->curr_ctx == ctx->num && dev->hw_lock) { | 974 | dev->curr_ctx == ctx->num && dev->hw_lock) { |
893 | ctx->state = MFCINST_ABORT; | 975 | ctx->state = MFCINST_ABORT; |
894 | s5p_mfc_wait_for_done_ctx(ctx, | 976 | s5p_mfc_wait_for_done_ctx(ctx, |
895 | S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0); | 977 | S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); |
896 | aborted = 1; | 978 | aborted = 1; |
897 | } | 979 | } |
898 | spin_lock_irqsave(&dev->irqlock, flags); | 980 | spin_lock_irqsave(&dev->irqlock, flags); |
899 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 981 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
900 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); | 982 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, |
983 | &ctx->vq_dst); | ||
901 | INIT_LIST_HEAD(&ctx->dst_queue); | 984 | INIT_LIST_HEAD(&ctx->dst_queue); |
902 | ctx->dst_queue_cnt = 0; | 985 | ctx->dst_queue_cnt = 0; |
903 | ctx->dpb_flush_flag = 1; | 986 | ctx->dpb_flush_flag = 1; |
904 | ctx->dec_dst_flag = 0; | 987 | ctx->dec_dst_flag = 0; |
905 | } | 988 | } |
906 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 989 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
907 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); | 990 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, |
991 | &ctx->vq_src); | ||
908 | INIT_LIST_HEAD(&ctx->src_queue); | 992 | INIT_LIST_HEAD(&ctx->src_queue); |
909 | ctx->src_queue_cnt = 0; | 993 | ctx->src_queue_cnt = 0; |
910 | } | 994 | } |
@@ -944,7 +1028,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) | |||
944 | } | 1028 | } |
945 | if (s5p_mfc_ctx_ready(ctx)) | 1029 | if (s5p_mfc_ctx_ready(ctx)) |
946 | set_work_bit_irqsave(ctx); | 1030 | set_work_bit_irqsave(ctx); |
947 | s5p_mfc_try_run(dev); | 1031 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
948 | } | 1032 | } |
949 | 1033 | ||
950 | static struct vb2_ops s5p_mfc_dec_qops = { | 1034 | static struct vb2_ops s5p_mfc_dec_qops = { |
@@ -1028,3 +1112,13 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx) | |||
1028 | ctx->ctrls[i] = NULL; | 1112 | ctx->ctrls[i] = NULL; |
1029 | } | 1113 | } |
1030 | 1114 | ||
1115 | void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx) | ||
1116 | { | ||
1117 | struct v4l2_format f; | ||
1118 | f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC; | ||
1119 | ctx->src_fmt = find_format(&f, MFC_FMT_DEC); | ||
1120 | f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC; | ||
1121 | ctx->dst_fmt = find_format(&f, MFC_FMT_RAW); | ||
1122 | mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n", | ||
1123 | (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt); | ||
1124 | } | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h index fdf1d99a9d15..d06a7cab5eb1 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h | |||
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void); | |||
19 | struct s5p_mfc_fmt *get_dec_def_fmt(bool src); | 19 | struct s5p_mfc_fmt *get_dec_def_fmt(bool src); |
20 | int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx); | 20 | int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx); |
21 | void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx); | 21 | void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx); |
22 | void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx); | ||
22 | 23 | ||
23 | #endif /* S5P_MFC_DEC_H_ */ | 24 | #endif /* S5P_MFC_DEC_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 179e4db60b15..2af6d522f4ac 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
@@ -25,48 +25,64 @@ | |||
25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <media/v4l2-ctrls.h> | 26 | #include <media/v4l2-ctrls.h> |
27 | #include <media/videobuf2-core.h> | 27 | #include <media/videobuf2-core.h> |
28 | #include "regs-mfc.h" | ||
29 | #include "s5p_mfc_common.h" | 28 | #include "s5p_mfc_common.h" |
30 | #include "s5p_mfc_debug.h" | 29 | #include "s5p_mfc_debug.h" |
31 | #include "s5p_mfc_enc.h" | 30 | #include "s5p_mfc_enc.h" |
32 | #include "s5p_mfc_intr.h" | 31 | #include "s5p_mfc_intr.h" |
33 | #include "s5p_mfc_opr.h" | 32 | #include "s5p_mfc_opr.h" |
34 | 33 | ||
34 | #define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12MT | ||
35 | #define DEF_DST_FMT_ENC V4L2_PIX_FMT_H264 | ||
36 | |||
35 | static struct s5p_mfc_fmt formats[] = { | 37 | static struct s5p_mfc_fmt formats[] = { |
36 | { | 38 | { |
37 | .name = "4:2:0 2 Planes 64x32 Tiles", | 39 | .name = "4:2:0 2 Planes 16x16 Tiles", |
38 | .fourcc = V4L2_PIX_FMT_NV12MT, | 40 | .fourcc = V4L2_PIX_FMT_NV12MT_16X16, |
39 | .codec_mode = S5P_FIMV_CODEC_NONE, | 41 | .codec_mode = S5P_MFC_CODEC_NONE, |
40 | .type = MFC_FMT_RAW, | 42 | .type = MFC_FMT_RAW, |
41 | .num_planes = 2, | 43 | .num_planes = 2, |
44 | }, | ||
45 | { | ||
46 | .name = "4:2:0 2 Planes 64x32 Tiles", | ||
47 | .fourcc = V4L2_PIX_FMT_NV12MT, | ||
48 | .codec_mode = S5P_MFC_CODEC_NONE, | ||
49 | .type = MFC_FMT_RAW, | ||
50 | .num_planes = 2, | ||
51 | }, | ||
52 | { | ||
53 | .name = "4:2:0 2 Planes Y/CbCr", | ||
54 | .fourcc = V4L2_PIX_FMT_NV12M, | ||
55 | .codec_mode = S5P_MFC_CODEC_NONE, | ||
56 | .type = MFC_FMT_RAW, | ||
57 | .num_planes = 2, | ||
42 | }, | 58 | }, |
43 | { | 59 | { |
44 | .name = "4:2:0 2 Planes", | 60 | .name = "4:2:0 2 Planes Y/CrCb", |
45 | .fourcc = V4L2_PIX_FMT_NV12M, | 61 | .fourcc = V4L2_PIX_FMT_NV21M, |
46 | .codec_mode = S5P_FIMV_CODEC_NONE, | 62 | .codec_mode = S5P_MFC_CODEC_NONE, |
47 | .type = MFC_FMT_RAW, | 63 | .type = MFC_FMT_RAW, |
48 | .num_planes = 2, | 64 | .num_planes = 2, |
49 | }, | 65 | }, |
50 | { | 66 | { |
51 | .name = "H264 Encoded Stream", | 67 | .name = "H264 Encoded Stream", |
52 | .fourcc = V4L2_PIX_FMT_H264, | 68 | .fourcc = V4L2_PIX_FMT_H264, |
53 | .codec_mode = S5P_FIMV_CODEC_H264_ENC, | 69 | .codec_mode = S5P_MFC_CODEC_H264_ENC, |
54 | .type = MFC_FMT_ENC, | 70 | .type = MFC_FMT_ENC, |
55 | .num_planes = 1, | 71 | .num_planes = 1, |
56 | }, | 72 | }, |
57 | { | 73 | { |
58 | .name = "MPEG4 Encoded Stream", | 74 | .name = "MPEG4 Encoded Stream", |
59 | .fourcc = V4L2_PIX_FMT_MPEG4, | 75 | .fourcc = V4L2_PIX_FMT_MPEG4, |
60 | .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC, | 76 | .codec_mode = S5P_MFC_CODEC_MPEG4_ENC, |
61 | .type = MFC_FMT_ENC, | 77 | .type = MFC_FMT_ENC, |
62 | .num_planes = 1, | 78 | .num_planes = 1, |
63 | }, | 79 | }, |
64 | { | 80 | { |
65 | .name = "H263 Encoded Stream", | 81 | .name = "H263 Encoded Stream", |
66 | .fourcc = V4L2_PIX_FMT_H263, | 82 | .fourcc = V4L2_PIX_FMT_H263, |
67 | .codec_mode = S5P_FIMV_CODEC_H263_ENC, | 83 | .codec_mode = S5P_MFC_CODEC_H263_ENC, |
68 | .type = MFC_FMT_ENC, | 84 | .type = MFC_FMT_ENC, |
69 | .num_planes = 1, | 85 | .num_planes = 1, |
70 | }, | 86 | }, |
71 | }; | 87 | }; |
72 | 88 | ||
@@ -574,7 +590,8 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) | |||
574 | if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1) | 590 | if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1) |
575 | return 1; | 591 | return 1; |
576 | /* context is ready to encode a frame */ | 592 | /* context is ready to encode a frame */ |
577 | if (ctx->state == MFCINST_RUNNING && | 593 | if ((ctx->state == MFCINST_RUNNING || |
594 | ctx->state == MFCINST_HEAD_PARSED) && | ||
578 | ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) | 595 | ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) |
579 | return 1; | 596 | return 1; |
580 | /* context is ready to encode remaining frames */ | 597 | /* context is ready to encode remaining frames */ |
@@ -619,7 +636,8 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx) | |||
619 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | 636 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); |
620 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | 637 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); |
621 | dst_size = vb2_plane_size(dst_mb->b, 0); | 638 | dst_size = vb2_plane_size(dst_mb->b, 0); |
622 | s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); | 639 | s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr, |
640 | dst_size); | ||
623 | spin_unlock_irqrestore(&dev->irqlock, flags); | 641 | spin_unlock_irqrestore(&dev->irqlock, flags); |
624 | return 0; | 642 | return 0; |
625 | } | 643 | } |
@@ -638,14 +656,23 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) | |||
638 | list_del(&dst_mb->list); | 656 | list_del(&dst_mb->list); |
639 | ctx->dst_queue_cnt--; | 657 | ctx->dst_queue_cnt--; |
640 | vb2_set_plane_payload(dst_mb->b, 0, | 658 | vb2_set_plane_payload(dst_mb->b, 0, |
641 | s5p_mfc_get_enc_strm_size()); | 659 | s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev)); |
642 | vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); | 660 | vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); |
643 | spin_unlock_irqrestore(&dev->irqlock, flags); | 661 | spin_unlock_irqrestore(&dev->irqlock, flags); |
644 | } | 662 | } |
645 | ctx->state = MFCINST_RUNNING; | 663 | if (IS_MFCV6(dev)) { |
646 | if (s5p_mfc_ctx_ready(ctx)) | 664 | ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */ |
647 | set_work_bit_irqsave(ctx); | 665 | } else { |
648 | s5p_mfc_try_run(dev); | 666 | ctx->state = MFCINST_RUNNING; |
667 | if (s5p_mfc_ctx_ready(ctx)) | ||
668 | set_work_bit_irqsave(ctx); | ||
669 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | ||
670 | } | ||
671 | |||
672 | if (IS_MFCV6(dev)) | ||
673 | ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, | ||
674 | get_enc_dpb_count, dev); | ||
675 | |||
649 | return 0; | 676 | return 0; |
650 | } | 677 | } |
651 | 678 | ||
@@ -662,14 +689,16 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx) | |||
662 | src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | 689 | src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); |
663 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); | 690 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); |
664 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); | 691 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); |
665 | s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr); | 692 | s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx, src_y_addr, |
693 | src_c_addr); | ||
666 | spin_unlock_irqrestore(&dev->irqlock, flags); | 694 | spin_unlock_irqrestore(&dev->irqlock, flags); |
667 | 695 | ||
668 | spin_lock_irqsave(&dev->irqlock, flags); | 696 | spin_lock_irqsave(&dev->irqlock, flags); |
669 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | 697 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); |
670 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | 698 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); |
671 | dst_size = vb2_plane_size(dst_mb->b, 0); | 699 | dst_size = vb2_plane_size(dst_mb->b, 0); |
672 | s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); | 700 | s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr, |
701 | dst_size); | ||
673 | spin_unlock_irqrestore(&dev->irqlock, flags); | 702 | spin_unlock_irqrestore(&dev->irqlock, flags); |
674 | 703 | ||
675 | return 0; | 704 | return 0; |
@@ -685,15 +714,16 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) | |||
685 | unsigned int strm_size; | 714 | unsigned int strm_size; |
686 | unsigned long flags; | 715 | unsigned long flags; |
687 | 716 | ||
688 | slice_type = s5p_mfc_get_enc_slice_type(); | 717 | slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev); |
689 | strm_size = s5p_mfc_get_enc_strm_size(); | 718 | strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev); |
690 | mfc_debug(2, "Encoded slice type: %d", slice_type); | 719 | mfc_debug(2, "Encoded slice type: %d", slice_type); |
691 | mfc_debug(2, "Encoded stream size: %d", strm_size); | 720 | mfc_debug(2, "Encoded stream size: %d", strm_size); |
692 | mfc_debug(2, "Display order: %d", | 721 | mfc_debug(2, "Display order: %d", |
693 | mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT)); | 722 | mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT)); |
694 | spin_lock_irqsave(&dev->irqlock, flags); | 723 | spin_lock_irqsave(&dev->irqlock, flags); |
695 | if (slice_type >= 0) { | 724 | if (slice_type >= 0) { |
696 | s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr); | 725 | s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx, |
726 | &enc_y_addr, &enc_c_addr); | ||
697 | list_for_each_entry(mb_entry, &ctx->src_queue, list) { | 727 | list_for_each_entry(mb_entry, &ctx->src_queue, list) { |
698 | mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0); | 728 | mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0); |
699 | mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1); | 729 | 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) | |||
939 | pix_fmt_mp->plane_fmt[0].bytesperline = 0; | 969 | pix_fmt_mp->plane_fmt[0].bytesperline = 0; |
940 | ctx->dst_bufs_cnt = 0; | 970 | ctx->dst_bufs_cnt = 0; |
941 | ctx->capture_state = QUEUE_FREE; | 971 | ctx->capture_state = QUEUE_FREE; |
942 | s5p_mfc_alloc_instance_buffer(ctx); | 972 | s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); |
943 | set_work_bit_irqsave(ctx); | 973 | set_work_bit_irqsave(ctx); |
944 | s5p_mfc_clean_ctx_int_flags(ctx); | 974 | s5p_mfc_clean_ctx_int_flags(ctx); |
945 | s5p_mfc_try_run(dev); | 975 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
946 | if (s5p_mfc_wait_for_done_ctx(ctx, \ | 976 | if (s5p_mfc_wait_for_done_ctx(ctx, \ |
947 | S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 1)) { | 977 | S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) { |
948 | /* Error or timeout */ | 978 | /* Error or timeout */ |
949 | mfc_err("Error getting instance from hardware\n"); | 979 | mfc_err("Error getting instance from hardware\n"); |
950 | s5p_mfc_release_instance_buffer(ctx); | 980 | s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, |
981 | ctx); | ||
951 | ret = -EIO; | 982 | ret = -EIO; |
952 | goto out; | 983 | goto out; |
953 | } | 984 | } |
@@ -958,6 +989,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
958 | mfc_err("failed to set output format\n"); | 989 | mfc_err("failed to set output format\n"); |
959 | return -EINVAL; | 990 | return -EINVAL; |
960 | } | 991 | } |
992 | |||
993 | if (!IS_MFCV6(dev) && | ||
994 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) { | ||
995 | mfc_err("Not supported format.\n"); | ||
996 | return -EINVAL; | ||
997 | } else if (IS_MFCV6(dev) && | ||
998 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
999 | mfc_err("Not supported format.\n"); | ||
1000 | return -EINVAL; | ||
1001 | } | ||
1002 | |||
961 | if (fmt->num_planes != pix_fmt_mp->num_planes) { | 1003 | if (fmt->num_planes != pix_fmt_mp->num_planes) { |
962 | mfc_err("failed to set output format\n"); | 1004 | mfc_err("failed to set output format\n"); |
963 | ret = -EINVAL; | 1005 | ret = -EINVAL; |
@@ -970,45 +1012,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
970 | mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n", | 1012 | mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n", |
971 | pix_fmt_mp->width, pix_fmt_mp->height, | 1013 | pix_fmt_mp->width, pix_fmt_mp->height, |
972 | ctx->img_width, ctx->img_height); | 1014 | ctx->img_width, ctx->img_height); |
973 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) { | 1015 | |
974 | ctx->buf_width = ALIGN(ctx->img_width, | 1016 | s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx); |
975 | S5P_FIMV_NV12M_HALIGN); | 1017 | pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size; |
976 | ctx->luma_size = ALIGN(ctx->img_width, | 1018 | pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width; |
977 | S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height, | 1019 | pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size; |
978 | S5P_FIMV_NV12M_LVALIGN); | 1020 | pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width; |
979 | ctx->chroma_size = ALIGN(ctx->img_width, | 1021 | |
980 | S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height | ||
981 | >> 1), S5P_FIMV_NV12M_CVALIGN); | ||
982 | |||
983 | ctx->luma_size = ALIGN(ctx->luma_size, | ||
984 | S5P_FIMV_NV12M_SALIGN); | ||
985 | ctx->chroma_size = ALIGN(ctx->chroma_size, | ||
986 | S5P_FIMV_NV12M_SALIGN); | ||
987 | |||
988 | pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size; | ||
989 | pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width; | ||
990 | pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size; | ||
991 | pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width; | ||
992 | |||
993 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) { | ||
994 | ctx->buf_width = ALIGN(ctx->img_width, | ||
995 | S5P_FIMV_NV12MT_HALIGN); | ||
996 | ctx->luma_size = ALIGN(ctx->img_width, | ||
997 | S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height, | ||
998 | S5P_FIMV_NV12MT_VALIGN); | ||
999 | ctx->chroma_size = ALIGN(ctx->img_width, | ||
1000 | S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height | ||
1001 | >> 1), S5P_FIMV_NV12MT_VALIGN); | ||
1002 | ctx->luma_size = ALIGN(ctx->luma_size, | ||
1003 | S5P_FIMV_NV12MT_SALIGN); | ||
1004 | ctx->chroma_size = ALIGN(ctx->chroma_size, | ||
1005 | S5P_FIMV_NV12MT_SALIGN); | ||
1006 | |||
1007 | pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size; | ||
1008 | pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width; | ||
1009 | pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size; | ||
1010 | pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width; | ||
1011 | } | ||
1012 | ctx->src_bufs_cnt = 0; | 1022 | ctx->src_bufs_cnt = 0; |
1013 | ctx->output_state = QUEUE_FREE; | 1023 | ctx->output_state = QUEUE_FREE; |
1014 | } else { | 1024 | } else { |
@@ -1023,6 +1033,7 @@ out: | |||
1023 | static int vidioc_reqbufs(struct file *file, void *priv, | 1033 | static int vidioc_reqbufs(struct file *file, void *priv, |
1024 | struct v4l2_requestbuffers *reqbufs) | 1034 | struct v4l2_requestbuffers *reqbufs) |
1025 | { | 1035 | { |
1036 | struct s5p_mfc_dev *dev = video_drvdata(file); | ||
1026 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | 1037 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
1027 | int ret = 0; | 1038 | int ret = 0; |
1028 | 1039 | ||
@@ -1042,12 +1053,16 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1042 | return ret; | 1053 | return ret; |
1043 | } | 1054 | } |
1044 | ctx->capture_state = QUEUE_BUFS_REQUESTED; | 1055 | ctx->capture_state = QUEUE_BUFS_REQUESTED; |
1045 | ret = s5p_mfc_alloc_codec_buffers(ctx); | 1056 | |
1046 | if (ret) { | 1057 | if (!IS_MFCV6(dev)) { |
1047 | mfc_err("Failed to allocate encoding buffers\n"); | 1058 | ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, |
1048 | reqbufs->count = 0; | 1059 | alloc_codec_buffers, ctx); |
1049 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | 1060 | if (ret) { |
1050 | return -ENOMEM; | 1061 | mfc_err("Failed to allocate encoding buffers\n"); |
1062 | reqbufs->count = 0; | ||
1063 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | ||
1064 | return -ENOMEM; | ||
1065 | } | ||
1051 | } | 1066 | } |
1052 | } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 1067 | } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
1053 | if (ctx->output_state != QUEUE_FREE) { | 1068 | if (ctx->output_state != QUEUE_FREE) { |
@@ -1310,6 +1325,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
1310 | p->codec.h264.profile = | 1325 | p->codec.h264.profile = |
1311 | S5P_FIMV_ENC_PROFILE_H264_BASELINE; | 1326 | S5P_FIMV_ENC_PROFILE_H264_BASELINE; |
1312 | break; | 1327 | break; |
1328 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: | ||
1329 | if (IS_MFCV6(dev)) | ||
1330 | p->codec.h264.profile = | ||
1331 | S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE; | ||
1332 | else | ||
1333 | ret = -EINVAL; | ||
1334 | break; | ||
1313 | default: | 1335 | default: |
1314 | ret = -EINVAL; | 1336 | ret = -EINVAL; |
1315 | } | 1337 | } |
@@ -1349,7 +1371,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
1349 | p->codec.h264._8x8_transform = ctrl->val; | 1371 | p->codec.h264._8x8_transform = ctrl->val; |
1350 | break; | 1372 | break; |
1351 | case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: | 1373 | case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: |
1352 | p->codec.h264.rc_mb = ctrl->val; | 1374 | p->rc_mb = ctrl->val; |
1353 | break; | 1375 | break; |
1354 | case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: | 1376 | case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: |
1355 | p->codec.h264.rc_frame_qp = ctrl->val; | 1377 | p->codec.h264.rc_frame_qp = ctrl->val; |
@@ -1500,7 +1522,7 @@ int vidioc_encoder_cmd(struct file *file, void *priv, | |||
1500 | mfc_debug(2, "EOS: empty src queue, entering finishing state"); | 1522 | mfc_debug(2, "EOS: empty src queue, entering finishing state"); |
1501 | ctx->state = MFCINST_FINISHING; | 1523 | ctx->state = MFCINST_FINISHING; |
1502 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1524 | spin_unlock_irqrestore(&dev->irqlock, flags); |
1503 | s5p_mfc_try_run(dev); | 1525 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
1504 | } else { | 1526 | } else { |
1505 | mfc_debug(2, "EOS: marking last buffer of stream"); | 1527 | mfc_debug(2, "EOS: marking last buffer of stream"); |
1506 | buf = list_entry(ctx->src_queue.prev, | 1528 | buf = list_entry(ctx->src_queue.prev, |
@@ -1583,6 +1605,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
1583 | unsigned int psize[], void *allocators[]) | 1605 | unsigned int psize[], void *allocators[]) |
1584 | { | 1606 | { |
1585 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | 1607 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); |
1608 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1586 | 1609 | ||
1587 | if (ctx->state != MFCINST_GOT_INST) { | 1610 | if (ctx->state != MFCINST_GOT_INST) { |
1588 | mfc_err("inavlid state: %d\n", ctx->state); | 1611 | mfc_err("inavlid state: %d\n", ctx->state); |
@@ -1611,8 +1634,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
1611 | *buf_count = MFC_MAX_BUFFERS; | 1634 | *buf_count = MFC_MAX_BUFFERS; |
1612 | psize[0] = ctx->luma_size; | 1635 | psize[0] = ctx->luma_size; |
1613 | psize[1] = ctx->chroma_size; | 1636 | psize[1] = ctx->chroma_size; |
1614 | allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | 1637 | if (IS_MFCV6(dev)) { |
1615 | allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | 1638 | allocators[0] = |
1639 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | ||
1640 | allocators[1] = | ||
1641 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | ||
1642 | } else { | ||
1643 | allocators[0] = | ||
1644 | ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | ||
1645 | allocators[1] = | ||
1646 | ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | ||
1647 | } | ||
1616 | } else { | 1648 | } else { |
1617 | mfc_err("inavlid queue type: %d\n", vq->type); | 1649 | mfc_err("inavlid queue type: %d\n", vq->type); |
1618 | return -EINVAL; | 1650 | return -EINVAL; |
@@ -1715,7 +1747,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) | |||
1715 | /* If context is ready then dev = work->data;schedule it to run */ | 1747 | /* If context is ready then dev = work->data;schedule it to run */ |
1716 | if (s5p_mfc_ctx_ready(ctx)) | 1748 | if (s5p_mfc_ctx_ready(ctx)) |
1717 | set_work_bit_irqsave(ctx); | 1749 | set_work_bit_irqsave(ctx); |
1718 | s5p_mfc_try_run(dev); | 1750 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
1719 | return 0; | 1751 | return 0; |
1720 | } | 1752 | } |
1721 | 1753 | ||
@@ -1729,19 +1761,21 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |||
1729 | ctx->state == MFCINST_RUNNING) && | 1761 | ctx->state == MFCINST_RUNNING) && |
1730 | dev->curr_ctx == ctx->num && dev->hw_lock) { | 1762 | dev->curr_ctx == ctx->num && dev->hw_lock) { |
1731 | ctx->state = MFCINST_ABORT; | 1763 | ctx->state = MFCINST_ABORT; |
1732 | s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET, | 1764 | s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET, |
1733 | 0); | 1765 | 0); |
1734 | } | 1766 | } |
1735 | ctx->state = MFCINST_FINISHED; | 1767 | ctx->state = MFCINST_FINISHED; |
1736 | spin_lock_irqsave(&dev->irqlock, flags); | 1768 | spin_lock_irqsave(&dev->irqlock, flags); |
1737 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 1769 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
1738 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); | 1770 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, |
1771 | &ctx->vq_dst); | ||
1739 | INIT_LIST_HEAD(&ctx->dst_queue); | 1772 | INIT_LIST_HEAD(&ctx->dst_queue); |
1740 | ctx->dst_queue_cnt = 0; | 1773 | ctx->dst_queue_cnt = 0; |
1741 | } | 1774 | } |
1742 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 1775 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
1743 | cleanup_ref_queue(ctx); | 1776 | cleanup_ref_queue(ctx); |
1744 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); | 1777 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, |
1778 | &ctx->vq_src); | ||
1745 | INIT_LIST_HEAD(&ctx->src_queue); | 1779 | INIT_LIST_HEAD(&ctx->src_queue); |
1746 | ctx->src_queue_cnt = 0; | 1780 | ctx->src_queue_cnt = 0; |
1747 | } | 1781 | } |
@@ -1782,7 +1816,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) | |||
1782 | } | 1816 | } |
1783 | if (s5p_mfc_ctx_ready(ctx)) | 1817 | if (s5p_mfc_ctx_ready(ctx)) |
1784 | set_work_bit_irqsave(ctx); | 1818 | set_work_bit_irqsave(ctx); |
1785 | s5p_mfc_try_run(dev); | 1819 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
1786 | } | 1820 | } |
1787 | 1821 | ||
1788 | static struct vb2_ops s5p_mfc_enc_qops = { | 1822 | static struct vb2_ops s5p_mfc_enc_qops = { |
@@ -1880,3 +1914,13 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx) | |||
1880 | for (i = 0; i < NUM_CTRLS; i++) | 1914 | for (i = 0; i < NUM_CTRLS; i++) |
1881 | ctx->ctrls[i] = NULL; | 1915 | ctx->ctrls[i] = NULL; |
1882 | } | 1916 | } |
1917 | |||
1918 | void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx) | ||
1919 | { | ||
1920 | struct v4l2_format f; | ||
1921 | f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC; | ||
1922 | ctx->src_fmt = find_format(&f, MFC_FMT_RAW); | ||
1923 | f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC; | ||
1924 | ctx->dst_fmt = find_format(&f, MFC_FMT_ENC); | ||
1925 | } | ||
1926 | |||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h index ca9fd66bd310..5118d46b3a9e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h | |||
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void); | |||
19 | struct s5p_mfc_fmt *get_enc_def_fmt(bool src); | 19 | struct s5p_mfc_fmt *get_enc_def_fmt(bool src); |
20 | int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx); | 20 | int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx); |
21 | void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx); | 21 | void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx); |
22 | void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx); | ||
22 | 23 | ||
23 | #endif /* S5P_MFC_ENC_H_ */ | 24 | #endif /* S5P_MFC_ENC_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c index 37860e299021..5b8f0e085e6d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
20 | #include "regs-mfc.h" | ||
21 | #include "s5p_mfc_common.h" | 20 | #include "s5p_mfc_common.h" |
22 | #include "s5p_mfc_debug.h" | 21 | #include "s5p_mfc_debug.h" |
23 | #include "s5p_mfc_intr.h" | 22 | #include "s5p_mfc_intr.h" |
@@ -28,7 +27,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command) | |||
28 | 27 | ||
29 | ret = wait_event_interruptible_timeout(dev->queue, | 28 | ret = wait_event_interruptible_timeout(dev->queue, |
30 | (dev->int_cond && (dev->int_type == command | 29 | (dev->int_cond && (dev->int_type == command |
31 | || dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET)), | 30 | || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)), |
32 | msecs_to_jiffies(MFC_INT_TIMEOUT)); | 31 | msecs_to_jiffies(MFC_INT_TIMEOUT)); |
33 | if (ret == 0) { | 32 | if (ret == 0) { |
34 | mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n", | 33 | 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) | |||
40 | } | 39 | } |
41 | mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n", | 40 | mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n", |
42 | dev->int_type, command); | 41 | dev->int_type, command); |
43 | if (dev->int_type == S5P_FIMV_R2H_CMD_ERR_RET) | 42 | if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET) |
44 | return 1; | 43 | return 1; |
45 | return 0; | 44 | return 0; |
46 | } | 45 | } |
@@ -60,12 +59,12 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, | |||
60 | if (interrupt) { | 59 | if (interrupt) { |
61 | ret = wait_event_interruptible_timeout(ctx->queue, | 60 | ret = wait_event_interruptible_timeout(ctx->queue, |
62 | (ctx->int_cond && (ctx->int_type == command | 61 | (ctx->int_cond && (ctx->int_type == command |
63 | || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)), | 62 | || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)), |
64 | msecs_to_jiffies(MFC_INT_TIMEOUT)); | 63 | msecs_to_jiffies(MFC_INT_TIMEOUT)); |
65 | } else { | 64 | } else { |
66 | ret = wait_event_timeout(ctx->queue, | 65 | ret = wait_event_timeout(ctx->queue, |
67 | (ctx->int_cond && (ctx->int_type == command | 66 | (ctx->int_cond && (ctx->int_type == command |
68 | || ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET)), | 67 | || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)), |
69 | msecs_to_jiffies(MFC_INT_TIMEOUT)); | 68 | msecs_to_jiffies(MFC_INT_TIMEOUT)); |
70 | } | 69 | } |
71 | if (ret == 0) { | 70 | if (ret == 0) { |
@@ -78,7 +77,7 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, | |||
78 | } | 77 | } |
79 | mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n", | 78 | mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n", |
80 | ctx->int_type, command); | 79 | ctx->int_type, command); |
81 | if (ctx->int_type == S5P_FIMV_R2H_CMD_ERR_RET) | 80 | if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET) |
82 | return 1; | 81 | return 1; |
83 | return 0; | 82 | return 0; |
84 | } | 83 | } |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 767a51271dc2..6932e90d4065 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.c | 2 | * drivers/media/platform/s5p-mfc/s5p_mfc_opr.c |
3 | * | 3 | * |
4 | * Samsung MFC (Multi Function Codec - FIMV) driver | 4 | * Samsung MFC (Multi Function Codec - FIMV) driver |
5 | * This file contains hw related functions. | 5 | * This file contains hw related functions. |
6 | * | 6 | * |
7 | * Kamil Debski, Copyright (c) 2011 Samsung Electronics | 7 | * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd. |
8 | * http://www.samsung.com/ | 8 | * http://www.samsung.com/ |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
@@ -12,1414 +12,20 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include "regs-mfc.h" | ||
16 | #include "s5p_mfc_cmd.h" | ||
17 | #include "s5p_mfc_common.h" | ||
18 | #include "s5p_mfc_ctrl.h" | ||
19 | #include "s5p_mfc_debug.h" | ||
20 | #include "s5p_mfc_intr.h" | ||
21 | #include "s5p_mfc_opr.h" | 15 | #include "s5p_mfc_opr.h" |
22 | #include "s5p_mfc_pm.h" | 16 | #include "s5p_mfc_opr_v5.h" |
23 | #include "s5p_mfc_shm.h" | 17 | #include "s5p_mfc_opr_v6.h" |
24 | #include <asm/cacheflush.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/firmware.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/jiffies.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/sched.h> | ||
33 | 18 | ||
34 | #define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT) | 19 | static struct s5p_mfc_hw_ops *s5p_mfc_ops; |
35 | #define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT) | ||
36 | 20 | ||
37 | /* Allocate temporary buffers for decoding */ | 21 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) |
38 | int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx) | ||
39 | { | 22 | { |
40 | void *desc_virt; | 23 | if (IS_MFCV6(dev)) { |
41 | struct s5p_mfc_dev *dev = ctx->dev; | 24 | s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); |
42 | 25 | dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; | |
43 | ctx->desc_buf = vb2_dma_contig_memops.alloc( | ||
44 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE); | ||
45 | if (IS_ERR_VALUE((int)ctx->desc_buf)) { | ||
46 | ctx->desc_buf = NULL; | ||
47 | mfc_err("Allocating DESC buffer failed\n"); | ||
48 | return -ENOMEM; | ||
49 | } | ||
50 | ctx->desc_phys = s5p_mfc_mem_cookie( | ||
51 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf); | ||
52 | BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
53 | desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf); | ||
54 | if (desc_virt == NULL) { | ||
55 | vb2_dma_contig_memops.put(ctx->desc_buf); | ||
56 | ctx->desc_phys = 0; | ||
57 | ctx->desc_buf = NULL; | ||
58 | mfc_err("Remapping DESC buffer failed\n"); | ||
59 | return -ENOMEM; | ||
60 | } | ||
61 | memset(desc_virt, 0, DESC_BUF_SIZE); | ||
62 | wmb(); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* Release temporary buffers for decoding */ | ||
67 | void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx) | ||
68 | { | ||
69 | if (ctx->desc_phys) { | ||
70 | vb2_dma_contig_memops.put(ctx->desc_buf); | ||
71 | ctx->desc_phys = 0; | ||
72 | ctx->desc_buf = NULL; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* Allocate codec buffers */ | ||
77 | int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx) | ||
78 | { | ||
79 | struct s5p_mfc_dev *dev = ctx->dev; | ||
80 | unsigned int enc_ref_y_size = 0; | ||
81 | unsigned int enc_ref_c_size = 0; | ||
82 | unsigned int guard_width, guard_height; | ||
83 | |||
84 | if (ctx->type == MFCINST_DECODER) { | ||
85 | mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", | ||
86 | ctx->luma_size, ctx->chroma_size, ctx->mv_size); | ||
87 | mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count); | ||
88 | } else if (ctx->type == MFCINST_ENCODER) { | ||
89 | enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
90 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | ||
91 | enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); | ||
92 | |||
93 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) { | ||
94 | enc_ref_c_size = ALIGN(ctx->img_width, | ||
95 | S5P_FIMV_NV12MT_HALIGN) | ||
96 | * ALIGN(ctx->img_height >> 1, | ||
97 | S5P_FIMV_NV12MT_VALIGN); | ||
98 | enc_ref_c_size = ALIGN(enc_ref_c_size, | ||
99 | S5P_FIMV_NV12MT_SALIGN); | ||
100 | } else { | ||
101 | guard_width = ALIGN(ctx->img_width + 16, | ||
102 | S5P_FIMV_NV12MT_HALIGN); | ||
103 | guard_height = ALIGN((ctx->img_height >> 1) + 4, | ||
104 | S5P_FIMV_NV12MT_VALIGN); | ||
105 | enc_ref_c_size = ALIGN(guard_width * guard_height, | ||
106 | S5P_FIMV_NV12MT_SALIGN); | ||
107 | } | ||
108 | mfc_debug(2, "recon luma size: %d chroma size: %d\n", | ||
109 | enc_ref_y_size, enc_ref_c_size); | ||
110 | } else { | 26 | } else { |
111 | return -EINVAL; | 27 | s5p_mfc_ops = s5p_mfc_init_hw_ops_v5(); |
112 | } | 28 | dev->warn_start = S5P_FIMV_ERR_WARNINGS_START; |
113 | /* Codecs have different memory requirements */ | ||
114 | switch (ctx->codec_mode) { | ||
115 | case S5P_FIMV_CODEC_H264_DEC: | ||
116 | ctx->bank1_size = | ||
117 | ALIGN(S5P_FIMV_DEC_NB_IP_SIZE + | ||
118 | S5P_FIMV_DEC_VERT_NB_MV_SIZE, | ||
119 | S5P_FIMV_DEC_BUF_ALIGN); | ||
120 | ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size; | ||
121 | break; | ||
122 | case S5P_FIMV_CODEC_MPEG4_DEC: | ||
123 | ctx->bank1_size = | ||
124 | ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE + | ||
125 | S5P_FIMV_DEC_UPNB_MV_SIZE + | ||
126 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | ||
127 | S5P_FIMV_DEC_STX_PARSER_SIZE + | ||
128 | S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE, | ||
129 | S5P_FIMV_DEC_BUF_ALIGN); | ||
130 | ctx->bank2_size = 0; | ||
131 | break; | ||
132 | case S5P_FIMV_CODEC_VC1RCV_DEC: | ||
133 | case S5P_FIMV_CODEC_VC1_DEC: | ||
134 | ctx->bank1_size = | ||
135 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + | ||
136 | S5P_FIMV_DEC_UPNB_MV_SIZE + | ||
137 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | ||
138 | S5P_FIMV_DEC_NB_DCAC_SIZE + | ||
139 | 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE, | ||
140 | S5P_FIMV_DEC_BUF_ALIGN); | ||
141 | ctx->bank2_size = 0; | ||
142 | break; | ||
143 | case S5P_FIMV_CODEC_MPEG2_DEC: | ||
144 | ctx->bank1_size = 0; | ||
145 | ctx->bank2_size = 0; | ||
146 | break; | ||
147 | case S5P_FIMV_CODEC_H263_DEC: | ||
148 | ctx->bank1_size = | ||
149 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + | ||
150 | S5P_FIMV_DEC_UPNB_MV_SIZE + | ||
151 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | ||
152 | S5P_FIMV_DEC_NB_DCAC_SIZE, | ||
153 | S5P_FIMV_DEC_BUF_ALIGN); | ||
154 | ctx->bank2_size = 0; | ||
155 | break; | ||
156 | case S5P_FIMV_CODEC_H264_ENC: | ||
157 | ctx->bank1_size = (enc_ref_y_size * 2) + | ||
158 | S5P_FIMV_ENC_UPMV_SIZE + | ||
159 | S5P_FIMV_ENC_COLFLG_SIZE + | ||
160 | S5P_FIMV_ENC_INTRAMD_SIZE + | ||
161 | S5P_FIMV_ENC_NBORINFO_SIZE; | ||
162 | ctx->bank2_size = (enc_ref_y_size * 2) + | ||
163 | (enc_ref_c_size * 4) + | ||
164 | S5P_FIMV_ENC_INTRAPRED_SIZE; | ||
165 | break; | ||
166 | case S5P_FIMV_CODEC_MPEG4_ENC: | ||
167 | ctx->bank1_size = (enc_ref_y_size * 2) + | ||
168 | S5P_FIMV_ENC_UPMV_SIZE + | ||
169 | S5P_FIMV_ENC_COLFLG_SIZE + | ||
170 | S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
171 | ctx->bank2_size = (enc_ref_y_size * 2) + | ||
172 | (enc_ref_c_size * 4); | ||
173 | break; | ||
174 | case S5P_FIMV_CODEC_H263_ENC: | ||
175 | ctx->bank1_size = (enc_ref_y_size * 2) + | ||
176 | S5P_FIMV_ENC_UPMV_SIZE + | ||
177 | S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
178 | ctx->bank2_size = (enc_ref_y_size * 2) + | ||
179 | (enc_ref_c_size * 4); | ||
180 | break; | ||
181 | default: | ||
182 | break; | ||
183 | } | ||
184 | /* Allocate only if memory from bank 1 is necessary */ | ||
185 | if (ctx->bank1_size > 0) { | ||
186 | ctx->bank1_buf = vb2_dma_contig_memops.alloc( | ||
187 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size); | ||
188 | if (IS_ERR(ctx->bank1_buf)) { | ||
189 | ctx->bank1_buf = NULL; | ||
190 | printk(KERN_ERR | ||
191 | "Buf alloc for decoding failed (port A)\n"); | ||
192 | return -ENOMEM; | ||
193 | } | ||
194 | ctx->bank1_phys = s5p_mfc_mem_cookie( | ||
195 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf); | ||
196 | BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
197 | } | ||
198 | /* Allocate only if memory from bank 2 is necessary */ | ||
199 | if (ctx->bank2_size > 0) { | ||
200 | ctx->bank2_buf = vb2_dma_contig_memops.alloc( | ||
201 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size); | ||
202 | if (IS_ERR(ctx->bank2_buf)) { | ||
203 | ctx->bank2_buf = NULL; | ||
204 | mfc_err("Buf alloc for decoding failed (port B)\n"); | ||
205 | return -ENOMEM; | ||
206 | } | ||
207 | ctx->bank2_phys = s5p_mfc_mem_cookie( | ||
208 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf); | ||
209 | BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); | ||
210 | } | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* Release buffers allocated for codec */ | ||
215 | void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx) | ||
216 | { | ||
217 | if (ctx->bank1_buf) { | ||
218 | vb2_dma_contig_memops.put(ctx->bank1_buf); | ||
219 | ctx->bank1_buf = NULL; | ||
220 | ctx->bank1_phys = 0; | ||
221 | ctx->bank1_size = 0; | ||
222 | } | ||
223 | if (ctx->bank2_buf) { | ||
224 | vb2_dma_contig_memops.put(ctx->bank2_buf); | ||
225 | ctx->bank2_buf = NULL; | ||
226 | ctx->bank2_phys = 0; | ||
227 | ctx->bank2_size = 0; | ||
228 | } | 29 | } |
30 | dev->mfc_ops = s5p_mfc_ops; | ||
229 | } | 31 | } |
230 | |||
231 | /* Allocate memory for instance data buffer */ | ||
232 | int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx) | ||
233 | { | ||
234 | void *context_virt; | ||
235 | struct s5p_mfc_dev *dev = ctx->dev; | ||
236 | |||
237 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC || | ||
238 | ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) | ||
239 | ctx->ctx_size = MFC_H264_CTX_BUF_SIZE; | ||
240 | else | ||
241 | ctx->ctx_size = MFC_CTX_BUF_SIZE; | ||
242 | ctx->ctx_buf = vb2_dma_contig_memops.alloc( | ||
243 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size); | ||
244 | if (IS_ERR(ctx->ctx_buf)) { | ||
245 | mfc_err("Allocating context buffer failed\n"); | ||
246 | ctx->ctx_phys = 0; | ||
247 | ctx->ctx_buf = NULL; | ||
248 | return -ENOMEM; | ||
249 | } | ||
250 | ctx->ctx_phys = s5p_mfc_mem_cookie( | ||
251 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf); | ||
252 | BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
253 | ctx->ctx_ofs = OFFSETA(ctx->ctx_phys); | ||
254 | context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf); | ||
255 | if (context_virt == NULL) { | ||
256 | mfc_err("Remapping instance buffer failed\n"); | ||
257 | vb2_dma_contig_memops.put(ctx->ctx_buf); | ||
258 | ctx->ctx_phys = 0; | ||
259 | ctx->ctx_buf = NULL; | ||
260 | return -ENOMEM; | ||
261 | } | ||
262 | /* Zero content of the allocated memory */ | ||
263 | memset(context_virt, 0, ctx->ctx_size); | ||
264 | wmb(); | ||
265 | if (s5p_mfc_init_shm(ctx) < 0) { | ||
266 | vb2_dma_contig_memops.put(ctx->ctx_buf); | ||
267 | ctx->ctx_phys = 0; | ||
268 | ctx->ctx_buf = NULL; | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | /* Release instance buffer */ | ||
275 | void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx) | ||
276 | { | ||
277 | if (ctx->ctx_buf) { | ||
278 | vb2_dma_contig_memops.put(ctx->ctx_buf); | ||
279 | ctx->ctx_phys = 0; | ||
280 | ctx->ctx_buf = NULL; | ||
281 | } | ||
282 | if (ctx->shm_alloc) { | ||
283 | vb2_dma_contig_memops.put(ctx->shm_alloc); | ||
284 | ctx->shm_alloc = NULL; | ||
285 | ctx->shm = NULL; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | /* Set registers for decoding temporary buffers */ | ||
290 | void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx) | ||
291 | { | ||
292 | struct s5p_mfc_dev *dev = ctx->dev; | ||
293 | |||
294 | mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR); | ||
295 | mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE); | ||
296 | } | ||
297 | |||
298 | /* Set registers for shared buffer */ | ||
299 | static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx) | ||
300 | { | ||
301 | struct s5p_mfc_dev *dev = ctx->dev; | ||
302 | mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR); | ||
303 | } | ||
304 | |||
305 | /* Set registers for decoding stream buffer */ | ||
306 | int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr, | ||
307 | unsigned int start_num_byte, unsigned int buf_size) | ||
308 | { | ||
309 | struct s5p_mfc_dev *dev = ctx->dev; | ||
310 | |||
311 | mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR); | ||
312 | mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE); | ||
313 | mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE); | ||
314 | s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM); | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | /* Set decoding frame buffer */ | ||
319 | int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx) | ||
320 | { | ||
321 | unsigned int frame_size, i; | ||
322 | unsigned int frame_size_ch, frame_size_mv; | ||
323 | struct s5p_mfc_dev *dev = ctx->dev; | ||
324 | unsigned int dpb; | ||
325 | size_t buf_addr1, buf_addr2; | ||
326 | int buf_size1, buf_size2; | ||
327 | |||
328 | buf_addr1 = ctx->bank1_phys; | ||
329 | buf_size1 = ctx->bank1_size; | ||
330 | buf_addr2 = ctx->bank2_phys; | ||
331 | buf_size2 = ctx->bank2_size; | ||
332 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & | ||
333 | ~S5P_FIMV_DPB_COUNT_MASK; | ||
334 | mfc_write(dev, ctx->total_dpb_count | dpb, | ||
335 | S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
336 | s5p_mfc_set_shared_buffer(ctx); | ||
337 | switch (ctx->codec_mode) { | ||
338 | case S5P_FIMV_CODEC_H264_DEC: | ||
339 | mfc_write(dev, OFFSETA(buf_addr1), | ||
340 | S5P_FIMV_H264_VERT_NB_MV_ADR); | ||
341 | buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE; | ||
342 | buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE; | ||
343 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR); | ||
344 | buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE; | ||
345 | buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE; | ||
346 | break; | ||
347 | case S5P_FIMV_CODEC_MPEG4_DEC: | ||
348 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR); | ||
349 | buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
350 | buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
351 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR); | ||
352 | buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
353 | buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
354 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR); | ||
355 | buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
356 | buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
357 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR); | ||
358 | buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE; | ||
359 | buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE; | ||
360 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR); | ||
361 | buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
362 | buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
363 | break; | ||
364 | case S5P_FIMV_CODEC_H263_DEC: | ||
365 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR); | ||
366 | buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
367 | buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
368 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR); | ||
369 | buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
370 | buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
371 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR); | ||
372 | buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
373 | buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
374 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR); | ||
375 | buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
376 | buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
377 | break; | ||
378 | case S5P_FIMV_CODEC_VC1_DEC: | ||
379 | case S5P_FIMV_CODEC_VC1RCV_DEC: | ||
380 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR); | ||
381 | buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
382 | buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
383 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR); | ||
384 | buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
385 | buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
386 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR); | ||
387 | buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
388 | buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
389 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR); | ||
390 | buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
391 | buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
392 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR); | ||
393 | buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
394 | buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
395 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR); | ||
396 | buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
397 | buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
398 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR); | ||
399 | buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
400 | buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
401 | break; | ||
402 | case S5P_FIMV_CODEC_MPEG2_DEC: | ||
403 | break; | ||
404 | default: | ||
405 | mfc_err("Unknown codec for decoding (%x)\n", | ||
406 | ctx->codec_mode); | ||
407 | return -EINVAL; | ||
408 | break; | ||
409 | } | ||
410 | frame_size = ctx->luma_size; | ||
411 | frame_size_ch = ctx->chroma_size; | ||
412 | frame_size_mv = ctx->mv_size; | ||
413 | mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch, | ||
414 | frame_size_mv); | ||
415 | for (i = 0; i < ctx->total_dpb_count; i++) { | ||
416 | /* Bank2 */ | ||
417 | mfc_debug(2, "Luma %d: %x\n", i, | ||
418 | ctx->dst_bufs[i].cookie.raw.luma); | ||
419 | mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma), | ||
420 | S5P_FIMV_DEC_LUMA_ADR + i * 4); | ||
421 | mfc_debug(2, "\tChroma %d: %x\n", i, | ||
422 | ctx->dst_bufs[i].cookie.raw.chroma); | ||
423 | mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma), | ||
424 | S5P_FIMV_DEC_CHROMA_ADR + i * 4); | ||
425 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) { | ||
426 | mfc_debug(2, "\tBuf2: %x, size: %d\n", | ||
427 | buf_addr2, buf_size2); | ||
428 | mfc_write(dev, OFFSETB(buf_addr2), | ||
429 | S5P_FIMV_H264_MV_ADR + i * 4); | ||
430 | buf_addr2 += frame_size_mv; | ||
431 | buf_size2 -= frame_size_mv; | ||
432 | } | ||
433 | } | ||
434 | mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1); | ||
435 | mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n", | ||
436 | buf_size1, buf_size2, ctx->total_dpb_count); | ||
437 | if (buf_size1 < 0 || buf_size2 < 0) { | ||
438 | mfc_debug(2, "Not enough memory has been allocated\n"); | ||
439 | return -ENOMEM; | ||
440 | } | ||
441 | s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE); | ||
442 | s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE); | ||
443 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) | ||
444 | s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE); | ||
445 | mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK) | ||
446 | << S5P_FIMV_CH_SHIFT) | (ctx->inst_no), | ||
447 | S5P_FIMV_SI_CH0_INST_ID); | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | /* Set registers for encoding stream buffer */ | ||
452 | int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx, | ||
453 | unsigned long addr, unsigned int size) | ||
454 | { | ||
455 | struct s5p_mfc_dev *dev = ctx->dev; | ||
456 | |||
457 | mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR); | ||
458 | mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx, | ||
463 | unsigned long y_addr, unsigned long c_addr) | ||
464 | { | ||
465 | struct s5p_mfc_dev *dev = ctx->dev; | ||
466 | |||
467 | mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR); | ||
468 | mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR); | ||
469 | } | ||
470 | |||
471 | void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx, | ||
472 | unsigned long *y_addr, unsigned long *c_addr) | ||
473 | { | ||
474 | struct s5p_mfc_dev *dev = ctx->dev; | ||
475 | |||
476 | *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) | ||
477 | << MFC_OFFSET_SHIFT); | ||
478 | *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) | ||
479 | << MFC_OFFSET_SHIFT); | ||
480 | } | ||
481 | |||
482 | /* Set encoding ref & codec buffer */ | ||
483 | int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx) | ||
484 | { | ||
485 | struct s5p_mfc_dev *dev = ctx->dev; | ||
486 | size_t buf_addr1, buf_addr2; | ||
487 | size_t buf_size1, buf_size2; | ||
488 | unsigned int enc_ref_y_size, enc_ref_c_size; | ||
489 | unsigned int guard_width, guard_height; | ||
490 | int i; | ||
491 | |||
492 | buf_addr1 = ctx->bank1_phys; | ||
493 | buf_size1 = ctx->bank1_size; | ||
494 | buf_addr2 = ctx->bank2_phys; | ||
495 | buf_size2 = ctx->bank2_size; | ||
496 | enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
497 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | ||
498 | enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); | ||
499 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) { | ||
500 | enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
501 | * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN); | ||
502 | enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN); | ||
503 | } else { | ||
504 | guard_width = ALIGN(ctx->img_width + 16, | ||
505 | S5P_FIMV_NV12MT_HALIGN); | ||
506 | guard_height = ALIGN((ctx->img_height >> 1) + 4, | ||
507 | S5P_FIMV_NV12MT_VALIGN); | ||
508 | enc_ref_c_size = ALIGN(guard_width * guard_height, | ||
509 | S5P_FIMV_NV12MT_SALIGN); | ||
510 | } | ||
511 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2); | ||
512 | switch (ctx->codec_mode) { | ||
513 | case S5P_FIMV_CODEC_H264_ENC: | ||
514 | for (i = 0; i < 2; i++) { | ||
515 | mfc_write(dev, OFFSETA(buf_addr1), | ||
516 | S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i)); | ||
517 | buf_addr1 += enc_ref_y_size; | ||
518 | buf_size1 -= enc_ref_y_size; | ||
519 | |||
520 | mfc_write(dev, OFFSETB(buf_addr2), | ||
521 | S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i)); | ||
522 | buf_addr2 += enc_ref_y_size; | ||
523 | buf_size2 -= enc_ref_y_size; | ||
524 | } | ||
525 | for (i = 0; i < 4; i++) { | ||
526 | mfc_write(dev, OFFSETB(buf_addr2), | ||
527 | S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i)); | ||
528 | buf_addr2 += enc_ref_c_size; | ||
529 | buf_size2 -= enc_ref_c_size; | ||
530 | } | ||
531 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR); | ||
532 | buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE; | ||
533 | buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE; | ||
534 | mfc_write(dev, OFFSETA(buf_addr1), | ||
535 | S5P_FIMV_H264_COZERO_FLAG_ADR); | ||
536 | buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE; | ||
537 | buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE; | ||
538 | mfc_write(dev, OFFSETA(buf_addr1), | ||
539 | S5P_FIMV_H264_UP_INTRA_MD_ADR); | ||
540 | buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE; | ||
541 | buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE; | ||
542 | mfc_write(dev, OFFSETB(buf_addr2), | ||
543 | S5P_FIMV_H264_UP_INTRA_PRED_ADR); | ||
544 | buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE; | ||
545 | buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE; | ||
546 | mfc_write(dev, OFFSETA(buf_addr1), | ||
547 | S5P_FIMV_H264_NBOR_INFO_ADR); | ||
548 | buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE; | ||
549 | buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE; | ||
550 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", | ||
551 | buf_size1, buf_size2); | ||
552 | break; | ||
553 | case S5P_FIMV_CODEC_MPEG4_ENC: | ||
554 | for (i = 0; i < 2; i++) { | ||
555 | mfc_write(dev, OFFSETA(buf_addr1), | ||
556 | S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i)); | ||
557 | buf_addr1 += enc_ref_y_size; | ||
558 | buf_size1 -= enc_ref_y_size; | ||
559 | mfc_write(dev, OFFSETB(buf_addr2), | ||
560 | S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i)); | ||
561 | buf_addr2 += enc_ref_y_size; | ||
562 | buf_size2 -= enc_ref_y_size; | ||
563 | } | ||
564 | for (i = 0; i < 4; i++) { | ||
565 | mfc_write(dev, OFFSETB(buf_addr2), | ||
566 | S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i)); | ||
567 | buf_addr2 += enc_ref_c_size; | ||
568 | buf_size2 -= enc_ref_c_size; | ||
569 | } | ||
570 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR); | ||
571 | buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE; | ||
572 | buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE; | ||
573 | mfc_write(dev, OFFSETA(buf_addr1), | ||
574 | S5P_FIMV_MPEG4_COZERO_FLAG_ADR); | ||
575 | buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE; | ||
576 | buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE; | ||
577 | mfc_write(dev, OFFSETA(buf_addr1), | ||
578 | S5P_FIMV_MPEG4_ACDC_COEF_ADR); | ||
579 | buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
580 | buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
581 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", | ||
582 | buf_size1, buf_size2); | ||
583 | break; | ||
584 | case S5P_FIMV_CODEC_H263_ENC: | ||
585 | for (i = 0; i < 2; i++) { | ||
586 | mfc_write(dev, OFFSETA(buf_addr1), | ||
587 | S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i)); | ||
588 | buf_addr1 += enc_ref_y_size; | ||
589 | buf_size1 -= enc_ref_y_size; | ||
590 | mfc_write(dev, OFFSETB(buf_addr2), | ||
591 | S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i)); | ||
592 | buf_addr2 += enc_ref_y_size; | ||
593 | buf_size2 -= enc_ref_y_size; | ||
594 | } | ||
595 | for (i = 0; i < 4; i++) { | ||
596 | mfc_write(dev, OFFSETB(buf_addr2), | ||
597 | S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i)); | ||
598 | buf_addr2 += enc_ref_c_size; | ||
599 | buf_size2 -= enc_ref_c_size; | ||
600 | } | ||
601 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR); | ||
602 | buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE; | ||
603 | buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE; | ||
604 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR); | ||
605 | buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
606 | buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
607 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", | ||
608 | buf_size1, buf_size2); | ||
609 | break; | ||
610 | default: | ||
611 | mfc_err("Unknown codec set for encoding: %d\n", | ||
612 | ctx->codec_mode); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) | ||
619 | { | ||
620 | struct s5p_mfc_dev *dev = ctx->dev; | ||
621 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
622 | unsigned int reg; | ||
623 | unsigned int shm; | ||
624 | |||
625 | /* width */ | ||
626 | mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX); | ||
627 | /* height */ | ||
628 | mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX); | ||
629 | /* pictype : enable, IDR period */ | ||
630 | reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
631 | reg |= (1 << 18); | ||
632 | reg &= ~(0xFFFF); | ||
633 | reg |= p->gop_size; | ||
634 | mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
635 | mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON); | ||
636 | /* multi-slice control */ | ||
637 | /* multi-slice MB number or bit size */ | ||
638 | mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL); | ||
639 | if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { | ||
640 | mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB); | ||
641 | } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { | ||
642 | mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT); | ||
643 | } else { | ||
644 | mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB); | ||
645 | mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT); | ||
646 | } | ||
647 | /* cyclic intra refresh */ | ||
648 | mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL); | ||
649 | /* memory structure cur. frame */ | ||
650 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) | ||
651 | mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
652 | else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) | ||
653 | mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
654 | /* padding control & value */ | ||
655 | reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL); | ||
656 | if (p->pad) { | ||
657 | /** enable */ | ||
658 | reg |= (1 << 31); | ||
659 | /** cr value */ | ||
660 | reg &= ~(0xFF << 16); | ||
661 | reg |= (p->pad_cr << 16); | ||
662 | /** cb value */ | ||
663 | reg &= ~(0xFF << 8); | ||
664 | reg |= (p->pad_cb << 8); | ||
665 | /** y value */ | ||
666 | reg &= ~(0xFF); | ||
667 | reg |= (p->pad_luma); | ||
668 | } else { | ||
669 | /** disable & all value clear */ | ||
670 | reg = 0; | ||
671 | } | ||
672 | mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL); | ||
673 | /* rate control config. */ | ||
674 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
675 | /** frame-level rate control */ | ||
676 | reg &= ~(0x1 << 9); | ||
677 | reg |= (p->rc_frame << 9); | ||
678 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
679 | /* bit rate */ | ||
680 | if (p->rc_frame) | ||
681 | mfc_write(dev, p->rc_bitrate, | ||
682 | S5P_FIMV_ENC_RC_BIT_RATE); | ||
683 | else | ||
684 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE); | ||
685 | /* reaction coefficient */ | ||
686 | if (p->rc_frame) | ||
687 | mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA); | ||
688 | shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL); | ||
689 | /* seq header ctrl */ | ||
690 | shm &= ~(0x1 << 3); | ||
691 | shm |= (p->seq_hdr_mode << 3); | ||
692 | /* frame skip mode */ | ||
693 | shm &= ~(0x3 << 1); | ||
694 | shm |= (p->frame_skip_mode << 1); | ||
695 | s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL); | ||
696 | /* fixed target bit */ | ||
697 | s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG); | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) | ||
702 | { | ||
703 | struct s5p_mfc_dev *dev = ctx->dev; | ||
704 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
705 | struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264; | ||
706 | unsigned int reg; | ||
707 | unsigned int shm; | ||
708 | |||
709 | s5p_mfc_set_enc_params(ctx); | ||
710 | /* pictype : number of B */ | ||
711 | reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
712 | /* num_b_frame - 0 ~ 2 */ | ||
713 | reg &= ~(0x3 << 16); | ||
714 | reg |= (p->num_b_frame << 16); | ||
715 | mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
716 | /* profile & level */ | ||
717 | reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE); | ||
718 | /* level */ | ||
719 | reg &= ~(0xFF << 8); | ||
720 | reg |= (p_264->level << 8); | ||
721 | /* profile - 0 ~ 2 */ | ||
722 | reg &= ~(0x3F); | ||
723 | reg |= p_264->profile; | ||
724 | mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE); | ||
725 | /* interlace */ | ||
726 | mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT); | ||
727 | /* height */ | ||
728 | if (p->interlace) | ||
729 | mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX); | ||
730 | /* loopfilter ctrl */ | ||
731 | mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL); | ||
732 | /* loopfilter alpha offset */ | ||
733 | if (p_264->loop_filter_alpha < 0) { | ||
734 | reg = 0x10; | ||
735 | reg |= (0xFF - p_264->loop_filter_alpha) + 1; | ||
736 | } else { | ||
737 | reg = 0x00; | ||
738 | reg |= (p_264->loop_filter_alpha & 0xF); | ||
739 | } | ||
740 | mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF); | ||
741 | /* loopfilter beta offset */ | ||
742 | if (p_264->loop_filter_beta < 0) { | ||
743 | reg = 0x10; | ||
744 | reg |= (0xFF - p_264->loop_filter_beta) + 1; | ||
745 | } else { | ||
746 | reg = 0x00; | ||
747 | reg |= (p_264->loop_filter_beta & 0xF); | ||
748 | } | ||
749 | mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF); | ||
750 | /* entropy coding mode */ | ||
751 | if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) | ||
752 | mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE); | ||
753 | else | ||
754 | mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE); | ||
755 | /* number of ref. picture */ | ||
756 | reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF); | ||
757 | /* num of ref. pictures of P */ | ||
758 | reg &= ~(0x3 << 5); | ||
759 | reg |= (p_264->num_ref_pic_4p << 5); | ||
760 | /* max number of ref. pictures */ | ||
761 | reg &= ~(0x1F); | ||
762 | reg |= p_264->max_ref_pic; | ||
763 | mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF); | ||
764 | /* 8x8 transform enable */ | ||
765 | mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG); | ||
766 | /* rate control config. */ | ||
767 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
768 | /* macroblock level rate control */ | ||
769 | reg &= ~(0x1 << 8); | ||
770 | reg |= (p_264->rc_mb << 8); | ||
771 | /* frame QP */ | ||
772 | reg &= ~(0x3F); | ||
773 | reg |= p_264->rc_frame_qp; | ||
774 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
775 | /* frame rate */ | ||
776 | if (p->rc_frame && p->rc_framerate_denom) | ||
777 | mfc_write(dev, p->rc_framerate_num * 1000 | ||
778 | / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
779 | else | ||
780 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
781 | /* max & min value of QP */ | ||
782 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND); | ||
783 | /* max QP */ | ||
784 | reg &= ~(0x3F << 8); | ||
785 | reg |= (p_264->rc_max_qp << 8); | ||
786 | /* min QP */ | ||
787 | reg &= ~(0x3F); | ||
788 | reg |= p_264->rc_min_qp; | ||
789 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND); | ||
790 | /* macroblock adaptive scaling features */ | ||
791 | if (p_264->rc_mb) { | ||
792 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL); | ||
793 | /* dark region */ | ||
794 | reg &= ~(0x1 << 3); | ||
795 | reg |= (p_264->rc_mb_dark << 3); | ||
796 | /* smooth region */ | ||
797 | reg &= ~(0x1 << 2); | ||
798 | reg |= (p_264->rc_mb_smooth << 2); | ||
799 | /* static region */ | ||
800 | reg &= ~(0x1 << 1); | ||
801 | reg |= (p_264->rc_mb_static << 1); | ||
802 | /* high activity region */ | ||
803 | reg &= ~(0x1); | ||
804 | reg |= p_264->rc_mb_activity; | ||
805 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL); | ||
806 | } | ||
807 | if (!p->rc_frame && | ||
808 | !p_264->rc_mb) { | ||
809 | shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP); | ||
810 | shm &= ~(0xFFF); | ||
811 | shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6); | ||
812 | shm |= (p_264->rc_p_frame_qp & 0x3F); | ||
813 | s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP); | ||
814 | } | ||
815 | /* extended encoder ctrl */ | ||
816 | shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL); | ||
817 | /* AR VUI control */ | ||
818 | shm &= ~(0x1 << 15); | ||
819 | shm |= (p_264->vui_sar << 1); | ||
820 | s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL); | ||
821 | if (p_264->vui_sar) { | ||
822 | /* aspect ration IDC */ | ||
823 | shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC); | ||
824 | shm &= ~(0xFF); | ||
825 | shm |= p_264->vui_sar_idc; | ||
826 | s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC); | ||
827 | if (p_264->vui_sar_idc == 0xFF) { | ||
828 | /* sample AR info */ | ||
829 | shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR); | ||
830 | shm &= ~(0xFFFFFFFF); | ||
831 | shm |= p_264->vui_ext_sar_width << 16; | ||
832 | shm |= p_264->vui_ext_sar_height; | ||
833 | s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR); | ||
834 | } | ||
835 | } | ||
836 | /* intra picture period for H.264 */ | ||
837 | shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD); | ||
838 | /* control */ | ||
839 | shm &= ~(0x1 << 16); | ||
840 | shm |= (p_264->open_gop << 16); | ||
841 | /* value */ | ||
842 | if (p_264->open_gop) { | ||
843 | shm &= ~(0xFFFF); | ||
844 | shm |= p_264->open_gop_size; | ||
845 | } | ||
846 | s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD); | ||
847 | /* extended encoder ctrl */ | ||
848 | shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL); | ||
849 | /* vbv buffer size */ | ||
850 | if (p->frame_skip_mode == | ||
851 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
852 | shm &= ~(0xFFFF << 16); | ||
853 | shm |= (p_264->cpb_size << 16); | ||
854 | } | ||
855 | s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL); | ||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) | ||
860 | { | ||
861 | struct s5p_mfc_dev *dev = ctx->dev; | ||
862 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
863 | struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4; | ||
864 | unsigned int reg; | ||
865 | unsigned int shm; | ||
866 | unsigned int framerate; | ||
867 | |||
868 | s5p_mfc_set_enc_params(ctx); | ||
869 | /* pictype : number of B */ | ||
870 | reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
871 | /* num_b_frame - 0 ~ 2 */ | ||
872 | reg &= ~(0x3 << 16); | ||
873 | reg |= (p->num_b_frame << 16); | ||
874 | mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
875 | /* profile & level */ | ||
876 | reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE); | ||
877 | /* level */ | ||
878 | reg &= ~(0xFF << 8); | ||
879 | reg |= (p_mpeg4->level << 8); | ||
880 | /* profile - 0 ~ 2 */ | ||
881 | reg &= ~(0x3F); | ||
882 | reg |= p_mpeg4->profile; | ||
883 | mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE); | ||
884 | /* quarter_pixel */ | ||
885 | mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL); | ||
886 | /* qp */ | ||
887 | if (!p->rc_frame) { | ||
888 | shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP); | ||
889 | shm &= ~(0xFFF); | ||
890 | shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6); | ||
891 | shm |= (p_mpeg4->rc_p_frame_qp & 0x3F); | ||
892 | s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP); | ||
893 | } | ||
894 | /* frame rate */ | ||
895 | if (p->rc_frame) { | ||
896 | if (p->rc_framerate_denom > 0) { | ||
897 | framerate = p->rc_framerate_num * 1000 / | ||
898 | p->rc_framerate_denom; | ||
899 | mfc_write(dev, framerate, | ||
900 | S5P_FIMV_ENC_RC_FRAME_RATE); | ||
901 | shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING); | ||
902 | shm &= ~(0xFFFFFFFF); | ||
903 | shm |= (1 << 31); | ||
904 | shm |= ((p->rc_framerate_num & 0x7FFF) << 16); | ||
905 | shm |= (p->rc_framerate_denom & 0xFFFF); | ||
906 | s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING); | ||
907 | } | ||
908 | } else { | ||
909 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
910 | } | ||
911 | /* rate control config. */ | ||
912 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
913 | /* frame QP */ | ||
914 | reg &= ~(0x3F); | ||
915 | reg |= p_mpeg4->rc_frame_qp; | ||
916 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
917 | /* max & min value of QP */ | ||
918 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND); | ||
919 | /* max QP */ | ||
920 | reg &= ~(0x3F << 8); | ||
921 | reg |= (p_mpeg4->rc_max_qp << 8); | ||
922 | /* min QP */ | ||
923 | reg &= ~(0x3F); | ||
924 | reg |= p_mpeg4->rc_min_qp; | ||
925 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND); | ||
926 | /* extended encoder ctrl */ | ||
927 | shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL); | ||
928 | /* vbv buffer size */ | ||
929 | if (p->frame_skip_mode == | ||
930 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
931 | shm &= ~(0xFFFF << 16); | ||
932 | shm |= (p->vbv_size << 16); | ||
933 | } | ||
934 | s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL); | ||
935 | return 0; | ||
936 | } | ||
937 | |||
938 | static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) | ||
939 | { | ||
940 | struct s5p_mfc_dev *dev = ctx->dev; | ||
941 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
942 | struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4; | ||
943 | unsigned int reg; | ||
944 | unsigned int shm; | ||
945 | |||
946 | s5p_mfc_set_enc_params(ctx); | ||
947 | /* qp */ | ||
948 | if (!p->rc_frame) { | ||
949 | shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP); | ||
950 | shm &= ~(0xFFF); | ||
951 | shm |= (p_h263->rc_p_frame_qp & 0x3F); | ||
952 | s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP); | ||
953 | } | ||
954 | /* frame rate */ | ||
955 | if (p->rc_frame && p->rc_framerate_denom) | ||
956 | mfc_write(dev, p->rc_framerate_num * 1000 | ||
957 | / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
958 | else | ||
959 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
960 | /* rate control config. */ | ||
961 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
962 | /* frame QP */ | ||
963 | reg &= ~(0x3F); | ||
964 | reg |= p_h263->rc_frame_qp; | ||
965 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
966 | /* max & min value of QP */ | ||
967 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND); | ||
968 | /* max QP */ | ||
969 | reg &= ~(0x3F << 8); | ||
970 | reg |= (p_h263->rc_max_qp << 8); | ||
971 | /* min QP */ | ||
972 | reg &= ~(0x3F); | ||
973 | reg |= p_h263->rc_min_qp; | ||
974 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND); | ||
975 | /* extended encoder ctrl */ | ||
976 | shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL); | ||
977 | /* vbv buffer size */ | ||
978 | if (p->frame_skip_mode == | ||
979 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
980 | shm &= ~(0xFFFF << 16); | ||
981 | shm |= (p->vbv_size << 16); | ||
982 | } | ||
983 | s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL); | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | /* Initialize decoding */ | ||
988 | int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx) | ||
989 | { | ||
990 | struct s5p_mfc_dev *dev = ctx->dev; | ||
991 | |||
992 | s5p_mfc_set_shared_buffer(ctx); | ||
993 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ | ||
994 | if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC) | ||
995 | mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL); | ||
996 | else | ||
997 | mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL); | ||
998 | mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) << | ||
999 | S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable << | ||
1000 | S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay & | ||
1001 | S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT), | ||
1002 | S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
1003 | mfc_write(dev, | ||
1004 | ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | ||
1005 | | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) | ||
1010 | { | ||
1011 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1012 | unsigned int dpb; | ||
1013 | |||
1014 | if (flush) | ||
1015 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | ( | ||
1016 | S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT); | ||
1017 | else | ||
1018 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & | ||
1019 | ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT); | ||
1020 | mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
1021 | } | ||
1022 | |||
1023 | /* Decode a single frame */ | ||
1024 | int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, | ||
1025 | enum s5p_mfc_decode_arg last_frame) | ||
1026 | { | ||
1027 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1028 | |||
1029 | mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF); | ||
1030 | s5p_mfc_set_shared_buffer(ctx); | ||
1031 | s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag); | ||
1032 | /* Issue different commands to instance basing on whether it | ||
1033 | * is the last frame or not. */ | ||
1034 | switch (last_frame) { | ||
1035 | case MFC_DEC_FRAME: | ||
1036 | mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) << | ||
1037 | S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1038 | break; | ||
1039 | case MFC_DEC_LAST_FRAME: | ||
1040 | mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) << | ||
1041 | S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1042 | break; | ||
1043 | case MFC_DEC_RES_CHANGE: | ||
1044 | mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC & | ||
1045 | S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no), | ||
1046 | S5P_FIMV_SI_CH0_INST_ID); | ||
1047 | break; | ||
1048 | } | ||
1049 | mfc_debug(2, "Decoding a usual frame\n"); | ||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1053 | int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx) | ||
1054 | { | ||
1055 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1056 | |||
1057 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC) | ||
1058 | s5p_mfc_set_enc_params_h264(ctx); | ||
1059 | else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC) | ||
1060 | s5p_mfc_set_enc_params_mpeg4(ctx); | ||
1061 | else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC) | ||
1062 | s5p_mfc_set_enc_params_h263(ctx); | ||
1063 | else { | ||
1064 | mfc_err("Unknown codec for encoding (%x)\n", | ||
1065 | ctx->codec_mode); | ||
1066 | return -EINVAL; | ||
1067 | } | ||
1068 | s5p_mfc_set_shared_buffer(ctx); | ||
1069 | mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) | | ||
1070 | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | /* Encode a single frame */ | ||
1075 | int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx) | ||
1076 | { | ||
1077 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1078 | int cmd; | ||
1079 | /* memory structure cur. frame */ | ||
1080 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) | ||
1081 | mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
1082 | else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) | ||
1083 | mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
1084 | s5p_mfc_set_shared_buffer(ctx); | ||
1085 | |||
1086 | if (ctx->state == MFCINST_FINISHING) | ||
1087 | cmd = S5P_FIMV_CH_LAST_FRAME; | ||
1088 | else | ||
1089 | cmd = S5P_FIMV_CH_FRAME_START; | ||
1090 | mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | ||
1091 | | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1092 | |||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) | ||
1097 | { | ||
1098 | unsigned long flags; | ||
1099 | int new_ctx; | ||
1100 | int cnt; | ||
1101 | |||
1102 | spin_lock_irqsave(&dev->condlock, flags); | ||
1103 | new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; | ||
1104 | cnt = 0; | ||
1105 | while (!test_bit(new_ctx, &dev->ctx_work_bits)) { | ||
1106 | new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS; | ||
1107 | if (++cnt > MFC_NUM_CONTEXTS) { | ||
1108 | /* No contexts to run */ | ||
1109 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
1110 | return -EAGAIN; | ||
1111 | } | ||
1112 | } | ||
1113 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
1114 | return new_ctx; | ||
1115 | } | ||
1116 | |||
1117 | static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx) | ||
1118 | { | ||
1119 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1120 | |||
1121 | s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0); | ||
1122 | dev->curr_ctx = ctx->num; | ||
1123 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1124 | s5p_mfc_decode_one_frame(ctx, MFC_DEC_RES_CHANGE); | ||
1125 | } | ||
1126 | |||
1127 | static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) | ||
1128 | { | ||
1129 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1130 | struct s5p_mfc_buf *temp_vb; | ||
1131 | unsigned long flags; | ||
1132 | unsigned int index; | ||
1133 | |||
1134 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1135 | /* Frames are being decoded */ | ||
1136 | if (list_empty(&ctx->src_queue)) { | ||
1137 | mfc_debug(2, "No src buffers\n"); | ||
1138 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1139 | return -EAGAIN; | ||
1140 | } | ||
1141 | /* Get the next source buffer */ | ||
1142 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1143 | temp_vb->flags |= MFC_BUF_FLAG_USED; | ||
1144 | s5p_mfc_set_dec_stream_buffer(ctx, | ||
1145 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream, | ||
1146 | temp_vb->b->v4l2_planes[0].bytesused); | ||
1147 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1148 | index = temp_vb->b->v4l2_buf.index; | ||
1149 | dev->curr_ctx = ctx->num; | ||
1150 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1151 | if (temp_vb->b->v4l2_planes[0].bytesused == 0) { | ||
1152 | last_frame = MFC_DEC_LAST_FRAME; | ||
1153 | mfc_debug(2, "Setting ctx->state to FINISHING\n"); | ||
1154 | ctx->state = MFCINST_FINISHING; | ||
1155 | } | ||
1156 | s5p_mfc_decode_one_frame(ctx, last_frame); | ||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | ||
1161 | { | ||
1162 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1163 | unsigned long flags; | ||
1164 | struct s5p_mfc_buf *dst_mb; | ||
1165 | struct s5p_mfc_buf *src_mb; | ||
1166 | unsigned long src_y_addr, src_c_addr, dst_addr; | ||
1167 | unsigned int dst_size; | ||
1168 | |||
1169 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1170 | if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) { | ||
1171 | mfc_debug(2, "no src buffers\n"); | ||
1172 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1173 | return -EAGAIN; | ||
1174 | } | ||
1175 | if (list_empty(&ctx->dst_queue)) { | ||
1176 | mfc_debug(2, "no dst buffers\n"); | ||
1177 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1178 | return -EAGAIN; | ||
1179 | } | ||
1180 | if (list_empty(&ctx->src_queue)) { | ||
1181 | /* send null frame */ | ||
1182 | s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2); | ||
1183 | src_mb = NULL; | ||
1184 | } else { | ||
1185 | src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, | ||
1186 | list); | ||
1187 | src_mb->flags |= MFC_BUF_FLAG_USED; | ||
1188 | if (src_mb->b->v4l2_planes[0].bytesused == 0) { | ||
1189 | /* send null frame */ | ||
1190 | s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, | ||
1191 | dev->bank2); | ||
1192 | ctx->state = MFCINST_FINISHING; | ||
1193 | } else { | ||
1194 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, | ||
1195 | 0); | ||
1196 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, | ||
1197 | 1); | ||
1198 | s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, | ||
1199 | src_c_addr); | ||
1200 | if (src_mb->flags & MFC_BUF_FLAG_EOS) | ||
1201 | ctx->state = MFCINST_FINISHING; | ||
1202 | } | ||
1203 | } | ||
1204 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | ||
1205 | dst_mb->flags |= MFC_BUF_FLAG_USED; | ||
1206 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | ||
1207 | dst_size = vb2_plane_size(dst_mb->b, 0); | ||
1208 | s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); | ||
1209 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1210 | dev->curr_ctx = ctx->num; | ||
1211 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1212 | mfc_debug(2, "encoding buffer with index=%d state=%d", | ||
1213 | src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); | ||
1214 | s5p_mfc_encode_one_frame(ctx); | ||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) | ||
1219 | { | ||
1220 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1221 | unsigned long flags; | ||
1222 | struct s5p_mfc_buf *temp_vb; | ||
1223 | |||
1224 | /* Initializing decoding - parsing header */ | ||
1225 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1226 | mfc_debug(2, "Preparing to init decoding\n"); | ||
1227 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1228 | s5p_mfc_set_dec_desc_buffer(ctx); | ||
1229 | mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); | ||
1230 | s5p_mfc_set_dec_stream_buffer(ctx, | ||
1231 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | ||
1232 | 0, temp_vb->b->v4l2_planes[0].bytesused); | ||
1233 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1234 | dev->curr_ctx = ctx->num; | ||
1235 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1236 | s5p_mfc_init_decode(ctx); | ||
1237 | } | ||
1238 | |||
1239 | static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) | ||
1240 | { | ||
1241 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1242 | unsigned long flags; | ||
1243 | struct s5p_mfc_buf *dst_mb; | ||
1244 | unsigned long dst_addr; | ||
1245 | unsigned int dst_size; | ||
1246 | |||
1247 | s5p_mfc_set_enc_ref_buffer(ctx); | ||
1248 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1249 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | ||
1250 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | ||
1251 | dst_size = vb2_plane_size(dst_mb->b, 0); | ||
1252 | s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); | ||
1253 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1254 | dev->curr_ctx = ctx->num; | ||
1255 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1256 | s5p_mfc_init_encode(ctx); | ||
1257 | } | ||
1258 | |||
1259 | static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) | ||
1260 | { | ||
1261 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1262 | unsigned long flags; | ||
1263 | struct s5p_mfc_buf *temp_vb; | ||
1264 | int ret; | ||
1265 | |||
1266 | /* | ||
1267 | * Header was parsed now starting processing | ||
1268 | * First set the output frame buffers | ||
1269 | */ | ||
1270 | if (ctx->capture_state != QUEUE_BUFS_MMAPED) { | ||
1271 | mfc_err("It seems that not all destionation buffers were " | ||
1272 | "mmaped\nMFC requires that all destination are mmaped " | ||
1273 | "before starting processing\n"); | ||
1274 | return -EAGAIN; | ||
1275 | } | ||
1276 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1277 | if (list_empty(&ctx->src_queue)) { | ||
1278 | mfc_err("Header has been deallocated in the middle of" | ||
1279 | " initialization\n"); | ||
1280 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1281 | return -EIO; | ||
1282 | } | ||
1283 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1284 | mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); | ||
1285 | s5p_mfc_set_dec_stream_buffer(ctx, | ||
1286 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | ||
1287 | 0, temp_vb->b->v4l2_planes[0].bytesused); | ||
1288 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1289 | dev->curr_ctx = ctx->num; | ||
1290 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1291 | ret = s5p_mfc_set_dec_frame_buffer(ctx); | ||
1292 | if (ret) { | ||
1293 | mfc_err("Failed to alloc frame mem\n"); | ||
1294 | ctx->state = MFCINST_ERROR; | ||
1295 | } | ||
1296 | return ret; | ||
1297 | } | ||
1298 | |||
1299 | /* Try running an operation on hardware */ | ||
1300 | void s5p_mfc_try_run(struct s5p_mfc_dev *dev) | ||
1301 | { | ||
1302 | struct s5p_mfc_ctx *ctx; | ||
1303 | int new_ctx; | ||
1304 | unsigned int ret = 0; | ||
1305 | |||
1306 | if (test_bit(0, &dev->enter_suspend)) { | ||
1307 | mfc_debug(1, "Entering suspend so do not schedule any jobs\n"); | ||
1308 | return; | ||
1309 | } | ||
1310 | /* Check whether hardware is not running */ | ||
1311 | if (test_and_set_bit(0, &dev->hw_lock) != 0) { | ||
1312 | /* This is perfectly ok, the scheduled ctx should wait */ | ||
1313 | mfc_debug(1, "Couldn't lock HW\n"); | ||
1314 | return; | ||
1315 | } | ||
1316 | /* Choose the context to run */ | ||
1317 | new_ctx = s5p_mfc_get_new_ctx(dev); | ||
1318 | if (new_ctx < 0) { | ||
1319 | /* No contexts to run */ | ||
1320 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) { | ||
1321 | mfc_err("Failed to unlock hardware\n"); | ||
1322 | return; | ||
1323 | } | ||
1324 | mfc_debug(1, "No ctx is scheduled to be run\n"); | ||
1325 | return; | ||
1326 | } | ||
1327 | ctx = dev->ctx[new_ctx]; | ||
1328 | /* Got context to run in ctx */ | ||
1329 | /* | ||
1330 | * Last frame has already been sent to MFC. | ||
1331 | * Now obtaining frames from MFC buffer | ||
1332 | */ | ||
1333 | s5p_mfc_clock_on(); | ||
1334 | if (ctx->type == MFCINST_DECODER) { | ||
1335 | s5p_mfc_set_dec_desc_buffer(ctx); | ||
1336 | switch (ctx->state) { | ||
1337 | case MFCINST_FINISHING: | ||
1338 | s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME); | ||
1339 | break; | ||
1340 | case MFCINST_RUNNING: | ||
1341 | ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME); | ||
1342 | break; | ||
1343 | case MFCINST_INIT: | ||
1344 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1345 | ret = s5p_mfc_open_inst_cmd(ctx); | ||
1346 | break; | ||
1347 | case MFCINST_RETURN_INST: | ||
1348 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1349 | ret = s5p_mfc_close_inst_cmd(ctx); | ||
1350 | break; | ||
1351 | case MFCINST_GOT_INST: | ||
1352 | s5p_mfc_run_init_dec(ctx); | ||
1353 | break; | ||
1354 | case MFCINST_HEAD_PARSED: | ||
1355 | ret = s5p_mfc_run_init_dec_buffers(ctx); | ||
1356 | mfc_debug(1, "head parsed\n"); | ||
1357 | break; | ||
1358 | case MFCINST_RES_CHANGE_INIT: | ||
1359 | s5p_mfc_run_res_change(ctx); | ||
1360 | break; | ||
1361 | case MFCINST_RES_CHANGE_FLUSH: | ||
1362 | s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME); | ||
1363 | break; | ||
1364 | case MFCINST_RES_CHANGE_END: | ||
1365 | mfc_debug(2, "Finished remaining frames after resolution change\n"); | ||
1366 | ctx->capture_state = QUEUE_FREE; | ||
1367 | mfc_debug(2, "Will re-init the codec\n"); | ||
1368 | s5p_mfc_run_init_dec(ctx); | ||
1369 | break; | ||
1370 | default: | ||
1371 | ret = -EAGAIN; | ||
1372 | } | ||
1373 | } else if (ctx->type == MFCINST_ENCODER) { | ||
1374 | switch (ctx->state) { | ||
1375 | case MFCINST_FINISHING: | ||
1376 | case MFCINST_RUNNING: | ||
1377 | ret = s5p_mfc_run_enc_frame(ctx); | ||
1378 | break; | ||
1379 | case MFCINST_INIT: | ||
1380 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1381 | ret = s5p_mfc_open_inst_cmd(ctx); | ||
1382 | break; | ||
1383 | case MFCINST_RETURN_INST: | ||
1384 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1385 | ret = s5p_mfc_close_inst_cmd(ctx); | ||
1386 | break; | ||
1387 | case MFCINST_GOT_INST: | ||
1388 | s5p_mfc_run_init_enc(ctx); | ||
1389 | break; | ||
1390 | default: | ||
1391 | ret = -EAGAIN; | ||
1392 | } | ||
1393 | } else { | ||
1394 | mfc_err("Invalid context type: %d\n", ctx->type); | ||
1395 | ret = -EAGAIN; | ||
1396 | } | ||
1397 | |||
1398 | if (ret) { | ||
1399 | /* Free hardware lock */ | ||
1400 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
1401 | mfc_err("Failed to unlock hardware\n"); | ||
1402 | |||
1403 | /* This is in deed imporant, as no operation has been | ||
1404 | * scheduled, reduce the clock count as no one will | ||
1405 | * ever do this, because no interrupt related to this try_run | ||
1406 | * will ever come from hardware. */ | ||
1407 | s5p_mfc_clock_off(); | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | |||
1412 | void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq) | ||
1413 | { | ||
1414 | struct s5p_mfc_buf *b; | ||
1415 | int i; | ||
1416 | |||
1417 | while (!list_empty(lh)) { | ||
1418 | b = list_entry(lh->next, struct s5p_mfc_buf, list); | ||
1419 | for (i = 0; i < b->b->num_planes; i++) | ||
1420 | vb2_set_plane_payload(b->b, i, 0); | ||
1421 | vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR); | ||
1422 | list_del(&b->list); | ||
1423 | } | ||
1424 | } | ||
1425 | |||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 2ad3def052f8..420abecafec0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.h | 2 | * drivers/media/platform/s5p-mfc/s5p_mfc_opr.h |
3 | * | 3 | * |
4 | * Header file for Samsung MFC (Multi Function Codec - FIMV) driver | 4 | * Header file for Samsung MFC (Multi Function Codec - FIMV) driver |
5 | * Contains declarations of hw related functions. | 5 | * Contains declarations of hw related functions. |
6 | * | 6 | * |
7 | * Kamil Debski, Copyright (C) 2011 Samsung Electronics | 7 | * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd. |
8 | * http://www.samsung.com/ | 8 | * http://www.samsung.com/ |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
@@ -17,77 +17,68 @@ | |||
17 | 17 | ||
18 | #include "s5p_mfc_common.h" | 18 | #include "s5p_mfc_common.h" |
19 | 19 | ||
20 | int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx); | 20 | struct s5p_mfc_hw_ops { |
21 | int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx); | 21 | int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx); |
22 | void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx); | ||
23 | int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx); | ||
24 | void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx); | ||
25 | int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx); | ||
26 | void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx); | ||
27 | int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev); | ||
28 | void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev); | ||
29 | void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx); | ||
30 | void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx); | ||
31 | int (*set_dec_stream_buffer)(struct s5p_mfc_ctx *ctx, | ||
32 | int buf_addr, unsigned int start_num_byte, | ||
33 | unsigned int buf_size); | ||
34 | int (*set_dec_frame_buffer)(struct s5p_mfc_ctx *ctx); | ||
35 | int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx, | ||
36 | unsigned long addr, unsigned int size); | ||
37 | void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx, | ||
38 | unsigned long y_addr, unsigned long c_addr); | ||
39 | void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx, | ||
40 | unsigned long *y_addr, unsigned long *c_addr); | ||
41 | int (*set_enc_ref_buffer)(struct s5p_mfc_ctx *ctx); | ||
42 | int (*init_decode)(struct s5p_mfc_ctx *ctx); | ||
43 | int (*init_encode)(struct s5p_mfc_ctx *ctx); | ||
44 | int (*encode_one_frame)(struct s5p_mfc_ctx *ctx); | ||
45 | void (*try_run)(struct s5p_mfc_dev *dev); | ||
46 | void (*cleanup_queue)(struct list_head *lh, | ||
47 | struct vb2_queue *vq); | ||
48 | void (*clear_int_flags)(struct s5p_mfc_dev *dev); | ||
49 | void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data, | ||
50 | unsigned int ofs); | ||
51 | unsigned int (*read_info)(struct s5p_mfc_ctx *ctx, | ||
52 | unsigned int ofs); | ||
53 | int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev); | ||
54 | int (*get_dec_y_adr)(struct s5p_mfc_dev *dev); | ||
55 | int (*get_dspl_status)(struct s5p_mfc_dev *dev); | ||
56 | int (*get_dec_status)(struct s5p_mfc_dev *dev); | ||
57 | int (*get_dec_frame_type)(struct s5p_mfc_dev *dev); | ||
58 | int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx); | ||
59 | int (*get_consumed_stream)(struct s5p_mfc_dev *dev); | ||
60 | int (*get_int_reason)(struct s5p_mfc_dev *dev); | ||
61 | int (*get_int_err)(struct s5p_mfc_dev *dev); | ||
62 | int (*err_dec)(unsigned int err); | ||
63 | int (*err_dspl)(unsigned int err); | ||
64 | int (*get_img_width)(struct s5p_mfc_dev *dev); | ||
65 | int (*get_img_height)(struct s5p_mfc_dev *dev); | ||
66 | int (*get_dpb_count)(struct s5p_mfc_dev *dev); | ||
67 | int (*get_mv_count)(struct s5p_mfc_dev *dev); | ||
68 | int (*get_inst_no)(struct s5p_mfc_dev *dev); | ||
69 | int (*get_enc_strm_size)(struct s5p_mfc_dev *dev); | ||
70 | int (*get_enc_slice_type)(struct s5p_mfc_dev *dev); | ||
71 | int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev); | ||
72 | int (*get_enc_pic_count)(struct s5p_mfc_dev *dev); | ||
73 | int (*get_sei_avail_status)(struct s5p_mfc_ctx *ctx); | ||
74 | int (*get_mvc_num_views)(struct s5p_mfc_dev *dev); | ||
75 | int (*get_mvc_view_id)(struct s5p_mfc_dev *dev); | ||
76 | unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx); | ||
77 | unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx); | ||
78 | unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx); | ||
79 | unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx); | ||
80 | }; | ||
22 | 81 | ||
23 | /* Decoding functions */ | 82 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); |
24 | int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx); | ||
25 | int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr, | ||
26 | unsigned int start_num_byte, | ||
27 | unsigned int buf_size); | ||
28 | |||
29 | /* Encoding functions */ | ||
30 | void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx, | ||
31 | unsigned long y_addr, unsigned long c_addr); | ||
32 | int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx, | ||
33 | unsigned long addr, unsigned int size); | ||
34 | void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx, | ||
35 | unsigned long *y_addr, unsigned long *c_addr); | ||
36 | int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx); | ||
37 | |||
38 | int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, | ||
39 | enum s5p_mfc_decode_arg last_frame); | ||
40 | int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx); | ||
41 | |||
42 | /* Memory allocation */ | ||
43 | int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx); | ||
44 | void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx); | ||
45 | void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx); | ||
46 | |||
47 | int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx); | ||
48 | void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx); | ||
49 | |||
50 | int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx); | ||
51 | void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx); | ||
52 | |||
53 | void s5p_mfc_try_run(struct s5p_mfc_dev *dev); | ||
54 | void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq); | ||
55 | |||
56 | #define s5p_mfc_get_dspl_y_adr() (readl(dev->regs_base + \ | ||
57 | S5P_FIMV_SI_DISPLAY_Y_ADR) << \ | ||
58 | MFC_OFFSET_SHIFT) | ||
59 | #define s5p_mfc_get_dec_y_adr() (readl(dev->regs_base + \ | ||
60 | S5P_FIMV_SI_DECODE_Y_ADR) << \ | ||
61 | MFC_OFFSET_SHIFT) | ||
62 | #define s5p_mfc_get_dspl_status() readl(dev->regs_base + \ | ||
63 | S5P_FIMV_SI_DISPLAY_STATUS) | ||
64 | #define s5p_mfc_get_dec_status() readl(dev->regs_base + \ | ||
65 | S5P_FIMV_SI_DECODE_STATUS) | ||
66 | #define s5p_mfc_get_frame_type() (readl(dev->regs_base + \ | ||
67 | S5P_FIMV_DECODE_FRAME_TYPE) \ | ||
68 | & S5P_FIMV_DECODE_FRAME_MASK) | ||
69 | #define s5p_mfc_get_consumed_stream() readl(dev->regs_base + \ | ||
70 | S5P_FIMV_SI_CONSUMED_BYTES) | ||
71 | #define s5p_mfc_get_int_reason() (readl(dev->regs_base + \ | ||
72 | S5P_FIMV_RISC2HOST_CMD) & \ | ||
73 | S5P_FIMV_RISC2HOST_CMD_MASK) | ||
74 | #define s5p_mfc_get_int_err() readl(dev->regs_base + \ | ||
75 | S5P_FIMV_RISC2HOST_ARG2) | ||
76 | #define s5p_mfc_err_dec(x) (((x) & S5P_FIMV_ERR_DEC_MASK) >> \ | ||
77 | S5P_FIMV_ERR_DEC_SHIFT) | ||
78 | #define s5p_mfc_err_dspl(x) (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \ | ||
79 | S5P_FIMV_ERR_DSPL_SHIFT) | ||
80 | #define s5p_mfc_get_img_width() readl(dev->regs_base + \ | ||
81 | S5P_FIMV_SI_HRESOL) | ||
82 | #define s5p_mfc_get_img_height() readl(dev->regs_base + \ | ||
83 | S5P_FIMV_SI_VRESOL) | ||
84 | #define s5p_mfc_get_dpb_count() readl(dev->regs_base + \ | ||
85 | S5P_FIMV_SI_BUF_NUMBER) | ||
86 | #define s5p_mfc_get_inst_no() readl(dev->regs_base + \ | ||
87 | S5P_FIMV_RISC2HOST_ARG1) | ||
88 | #define s5p_mfc_get_enc_strm_size() readl(dev->regs_base + \ | ||
89 | S5P_FIMV_ENC_SI_STRM_SIZE) | ||
90 | #define s5p_mfc_get_enc_slice_type() readl(dev->regs_base + \ | ||
91 | S5P_FIMV_ENC_SI_SLICE_TYPE) | ||
92 | 83 | ||
93 | #endif /* S5P_MFC_OPR_H_ */ | 84 | #endif /* S5P_MFC_OPR_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c new file mode 100644 index 000000000000..bf7d010a4107 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | |||
@@ -0,0 +1,1794 @@ | |||
1 | /* | ||
2 | * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c | ||
3 | * | ||
4 | * Samsung MFC (Multi Function Codec - FIMV) driver | ||
5 | * This file contains hw related functions. | ||
6 | * | ||
7 | * Kamil Debski, Copyright (c) 2011 Samsung Electronics | ||
8 | * http://www.samsung.com/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include "s5p_mfc_common.h" | ||
16 | #include "s5p_mfc_cmd.h" | ||
17 | #include "s5p_mfc_ctrl.h" | ||
18 | #include "s5p_mfc_debug.h" | ||
19 | #include "s5p_mfc_intr.h" | ||
20 | #include "s5p_mfc_pm.h" | ||
21 | #include "s5p_mfc_opr.h" | ||
22 | #include "s5p_mfc_opr_v5.h" | ||
23 | #include <asm/cacheflush.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/firmware.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/jiffies.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/sched.h> | ||
32 | |||
33 | #define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT) | ||
34 | #define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT) | ||
35 | |||
36 | /* Allocate temporary buffers for decoding */ | ||
37 | int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) | ||
38 | { | ||
39 | struct s5p_mfc_dev *dev = ctx->dev; | ||
40 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; | ||
41 | |||
42 | ctx->dsc.alloc = vb2_dma_contig_memops.alloc( | ||
43 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], | ||
44 | buf_size->dsc); | ||
45 | if (IS_ERR_VALUE((int)ctx->dsc.alloc)) { | ||
46 | ctx->dsc.alloc = NULL; | ||
47 | mfc_err("Allocating DESC buffer failed\n"); | ||
48 | return -ENOMEM; | ||
49 | } | ||
50 | ctx->dsc.dma = s5p_mfc_mem_cookie( | ||
51 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc); | ||
52 | BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
53 | ctx->dsc.virt = vb2_dma_contig_memops.vaddr(ctx->dsc.alloc); | ||
54 | if (ctx->dsc.virt == NULL) { | ||
55 | vb2_dma_contig_memops.put(ctx->dsc.alloc); | ||
56 | ctx->dsc.dma = 0; | ||
57 | ctx->dsc.alloc = NULL; | ||
58 | mfc_err("Remapping DESC buffer failed\n"); | ||
59 | return -ENOMEM; | ||
60 | } | ||
61 | memset(ctx->dsc.virt, 0, buf_size->dsc); | ||
62 | wmb(); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* Release temporary buffers for decoding */ | ||
67 | void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) | ||
68 | { | ||
69 | if (ctx->dsc.dma) { | ||
70 | vb2_dma_contig_memops.put(ctx->dsc.alloc); | ||
71 | ctx->dsc.alloc = NULL; | ||
72 | ctx->dsc.dma = 0; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* Allocate codec buffers */ | ||
77 | int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) | ||
78 | { | ||
79 | struct s5p_mfc_dev *dev = ctx->dev; | ||
80 | unsigned int enc_ref_y_size = 0; | ||
81 | unsigned int enc_ref_c_size = 0; | ||
82 | unsigned int guard_width, guard_height; | ||
83 | |||
84 | if (ctx->type == MFCINST_DECODER) { | ||
85 | mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", | ||
86 | ctx->luma_size, ctx->chroma_size, ctx->mv_size); | ||
87 | mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count); | ||
88 | } else if (ctx->type == MFCINST_ENCODER) { | ||
89 | enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
90 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | ||
91 | enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); | ||
92 | |||
93 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) { | ||
94 | enc_ref_c_size = ALIGN(ctx->img_width, | ||
95 | S5P_FIMV_NV12MT_HALIGN) | ||
96 | * ALIGN(ctx->img_height >> 1, | ||
97 | S5P_FIMV_NV12MT_VALIGN); | ||
98 | enc_ref_c_size = ALIGN(enc_ref_c_size, | ||
99 | S5P_FIMV_NV12MT_SALIGN); | ||
100 | } else { | ||
101 | guard_width = ALIGN(ctx->img_width + 16, | ||
102 | S5P_FIMV_NV12MT_HALIGN); | ||
103 | guard_height = ALIGN((ctx->img_height >> 1) + 4, | ||
104 | S5P_FIMV_NV12MT_VALIGN); | ||
105 | enc_ref_c_size = ALIGN(guard_width * guard_height, | ||
106 | S5P_FIMV_NV12MT_SALIGN); | ||
107 | } | ||
108 | mfc_debug(2, "recon luma size: %d chroma size: %d\n", | ||
109 | enc_ref_y_size, enc_ref_c_size); | ||
110 | } else { | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | /* Codecs have different memory requirements */ | ||
114 | switch (ctx->codec_mode) { | ||
115 | case S5P_MFC_CODEC_H264_DEC: | ||
116 | ctx->bank1_size = | ||
117 | ALIGN(S5P_FIMV_DEC_NB_IP_SIZE + | ||
118 | S5P_FIMV_DEC_VERT_NB_MV_SIZE, | ||
119 | S5P_FIMV_DEC_BUF_ALIGN); | ||
120 | ctx->bank2_size = ctx->total_dpb_count * ctx->mv_size; | ||
121 | break; | ||
122 | case S5P_MFC_CODEC_MPEG4_DEC: | ||
123 | ctx->bank1_size = | ||
124 | ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE + | ||
125 | S5P_FIMV_DEC_UPNB_MV_SIZE + | ||
126 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | ||
127 | S5P_FIMV_DEC_STX_PARSER_SIZE + | ||
128 | S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE, | ||
129 | S5P_FIMV_DEC_BUF_ALIGN); | ||
130 | ctx->bank2_size = 0; | ||
131 | break; | ||
132 | case S5P_MFC_CODEC_VC1RCV_DEC: | ||
133 | case S5P_MFC_CODEC_VC1_DEC: | ||
134 | ctx->bank1_size = | ||
135 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + | ||
136 | S5P_FIMV_DEC_UPNB_MV_SIZE + | ||
137 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | ||
138 | S5P_FIMV_DEC_NB_DCAC_SIZE + | ||
139 | 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE, | ||
140 | S5P_FIMV_DEC_BUF_ALIGN); | ||
141 | ctx->bank2_size = 0; | ||
142 | break; | ||
143 | case S5P_MFC_CODEC_MPEG2_DEC: | ||
144 | ctx->bank1_size = 0; | ||
145 | ctx->bank2_size = 0; | ||
146 | break; | ||
147 | case S5P_MFC_CODEC_H263_DEC: | ||
148 | ctx->bank1_size = | ||
149 | ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE + | ||
150 | S5P_FIMV_DEC_UPNB_MV_SIZE + | ||
151 | S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE + | ||
152 | S5P_FIMV_DEC_NB_DCAC_SIZE, | ||
153 | S5P_FIMV_DEC_BUF_ALIGN); | ||
154 | ctx->bank2_size = 0; | ||
155 | break; | ||
156 | case S5P_MFC_CODEC_H264_ENC: | ||
157 | ctx->bank1_size = (enc_ref_y_size * 2) + | ||
158 | S5P_FIMV_ENC_UPMV_SIZE + | ||
159 | S5P_FIMV_ENC_COLFLG_SIZE + | ||
160 | S5P_FIMV_ENC_INTRAMD_SIZE + | ||
161 | S5P_FIMV_ENC_NBORINFO_SIZE; | ||
162 | ctx->bank2_size = (enc_ref_y_size * 2) + | ||
163 | (enc_ref_c_size * 4) + | ||
164 | S5P_FIMV_ENC_INTRAPRED_SIZE; | ||
165 | break; | ||
166 | case S5P_MFC_CODEC_MPEG4_ENC: | ||
167 | ctx->bank1_size = (enc_ref_y_size * 2) + | ||
168 | S5P_FIMV_ENC_UPMV_SIZE + | ||
169 | S5P_FIMV_ENC_COLFLG_SIZE + | ||
170 | S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
171 | ctx->bank2_size = (enc_ref_y_size * 2) + | ||
172 | (enc_ref_c_size * 4); | ||
173 | break; | ||
174 | case S5P_MFC_CODEC_H263_ENC: | ||
175 | ctx->bank1_size = (enc_ref_y_size * 2) + | ||
176 | S5P_FIMV_ENC_UPMV_SIZE + | ||
177 | S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
178 | ctx->bank2_size = (enc_ref_y_size * 2) + | ||
179 | (enc_ref_c_size * 4); | ||
180 | break; | ||
181 | default: | ||
182 | break; | ||
183 | } | ||
184 | /* Allocate only if memory from bank 1 is necessary */ | ||
185 | if (ctx->bank1_size > 0) { | ||
186 | ctx->bank1_buf = vb2_dma_contig_memops.alloc( | ||
187 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size); | ||
188 | if (IS_ERR(ctx->bank1_buf)) { | ||
189 | ctx->bank1_buf = NULL; | ||
190 | printk(KERN_ERR | ||
191 | "Buf alloc for decoding failed (port A)\n"); | ||
192 | return -ENOMEM; | ||
193 | } | ||
194 | ctx->bank1_phys = s5p_mfc_mem_cookie( | ||
195 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf); | ||
196 | BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
197 | } | ||
198 | /* Allocate only if memory from bank 2 is necessary */ | ||
199 | if (ctx->bank2_size > 0) { | ||
200 | ctx->bank2_buf = vb2_dma_contig_memops.alloc( | ||
201 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_size); | ||
202 | if (IS_ERR(ctx->bank2_buf)) { | ||
203 | ctx->bank2_buf = NULL; | ||
204 | mfc_err("Buf alloc for decoding failed (port B)\n"); | ||
205 | return -ENOMEM; | ||
206 | } | ||
207 | ctx->bank2_phys = s5p_mfc_mem_cookie( | ||
208 | dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], ctx->bank2_buf); | ||
209 | BUG_ON(ctx->bank2_phys & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); | ||
210 | } | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* Release buffers allocated for codec */ | ||
215 | void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) | ||
216 | { | ||
217 | if (ctx->bank1_buf) { | ||
218 | vb2_dma_contig_memops.put(ctx->bank1_buf); | ||
219 | ctx->bank1_buf = NULL; | ||
220 | ctx->bank1_phys = 0; | ||
221 | ctx->bank1_size = 0; | ||
222 | } | ||
223 | if (ctx->bank2_buf) { | ||
224 | vb2_dma_contig_memops.put(ctx->bank2_buf); | ||
225 | ctx->bank2_buf = NULL; | ||
226 | ctx->bank2_phys = 0; | ||
227 | ctx->bank2_size = 0; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* Allocate memory for instance data buffer */ | ||
232 | int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) | ||
233 | { | ||
234 | struct s5p_mfc_dev *dev = ctx->dev; | ||
235 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; | ||
236 | |||
237 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | ||
238 | ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | ||
239 | ctx->ctx.size = buf_size->h264_ctx; | ||
240 | else | ||
241 | ctx->ctx.size = buf_size->non_h264_ctx; | ||
242 | ctx->ctx.alloc = vb2_dma_contig_memops.alloc( | ||
243 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size); | ||
244 | if (IS_ERR(ctx->ctx.alloc)) { | ||
245 | mfc_err("Allocating context buffer failed\n"); | ||
246 | ctx->ctx.alloc = NULL; | ||
247 | return -ENOMEM; | ||
248 | } | ||
249 | ctx->ctx.dma = s5p_mfc_mem_cookie( | ||
250 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc); | ||
251 | BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
252 | ctx->ctx.ofs = OFFSETA(ctx->ctx.dma); | ||
253 | ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc); | ||
254 | if (!ctx->ctx.virt) { | ||
255 | mfc_err("Remapping instance buffer failed\n"); | ||
256 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
257 | ctx->ctx.alloc = NULL; | ||
258 | ctx->ctx.ofs = 0; | ||
259 | ctx->ctx.dma = 0; | ||
260 | return -ENOMEM; | ||
261 | } | ||
262 | /* Zero content of the allocated memory */ | ||
263 | memset(ctx->ctx.virt, 0, ctx->ctx.size); | ||
264 | wmb(); | ||
265 | |||
266 | /* Initialize shared memory */ | ||
267 | ctx->shm.alloc = vb2_dma_contig_memops.alloc( | ||
268 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->shm); | ||
269 | if (IS_ERR(ctx->shm.alloc)) { | ||
270 | mfc_err("failed to allocate shared memory\n"); | ||
271 | return PTR_ERR(ctx->shm.alloc); | ||
272 | } | ||
273 | /* shared memory offset only keeps the offset from base (port a) */ | ||
274 | ctx->shm.ofs = s5p_mfc_mem_cookie( | ||
275 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->shm.alloc) | ||
276 | - dev->bank1; | ||
277 | BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
278 | |||
279 | ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc); | ||
280 | if (!ctx->shm.virt) { | ||
281 | vb2_dma_contig_memops.put(ctx->shm.alloc); | ||
282 | ctx->shm.alloc = NULL; | ||
283 | ctx->shm.ofs = 0; | ||
284 | mfc_err("failed to virt addr of shared memory\n"); | ||
285 | return -ENOMEM; | ||
286 | } | ||
287 | memset((void *)ctx->shm.virt, 0, buf_size->shm); | ||
288 | wmb(); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /* Release instance buffer */ | ||
293 | void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) | ||
294 | { | ||
295 | if (ctx->ctx.alloc) { | ||
296 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
297 | ctx->ctx.alloc = NULL; | ||
298 | ctx->ctx.ofs = 0; | ||
299 | ctx->ctx.virt = NULL; | ||
300 | ctx->ctx.dma = 0; | ||
301 | } | ||
302 | if (ctx->shm.alloc) { | ||
303 | vb2_dma_contig_memops.put(ctx->shm.alloc); | ||
304 | ctx->shm.alloc = NULL; | ||
305 | ctx->shm.ofs = 0; | ||
306 | ctx->shm.virt = NULL; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) | ||
311 | { | ||
312 | /* NOP */ | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev) | ||
318 | { | ||
319 | /* NOP */ | ||
320 | } | ||
321 | |||
322 | static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data, | ||
323 | unsigned int ofs) | ||
324 | { | ||
325 | writel(data, (ctx->shm.virt + ofs)); | ||
326 | wmb(); | ||
327 | } | ||
328 | |||
329 | static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx, | ||
330 | unsigned int ofs) | ||
331 | { | ||
332 | rmb(); | ||
333 | return readl(ctx->shm.virt + ofs); | ||
334 | } | ||
335 | |||
336 | void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx) | ||
337 | { | ||
338 | unsigned int guard_width, guard_height; | ||
339 | |||
340 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN); | ||
341 | ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | ||
342 | mfc_debug(2, | ||
343 | "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n", | ||
344 | ctx->img_width, ctx->img_height, ctx->buf_width, | ||
345 | ctx->buf_height); | ||
346 | |||
347 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) { | ||
348 | ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height, | ||
349 | S5P_FIMV_DEC_BUF_ALIGN); | ||
350 | ctx->chroma_size = ALIGN(ctx->buf_width * | ||
351 | ALIGN((ctx->img_height >> 1), | ||
352 | S5P_FIMV_NV12MT_VALIGN), | ||
353 | S5P_FIMV_DEC_BUF_ALIGN); | ||
354 | ctx->mv_size = ALIGN(ctx->buf_width * | ||
355 | ALIGN((ctx->buf_height >> 2), | ||
356 | S5P_FIMV_NV12MT_VALIGN), | ||
357 | S5P_FIMV_DEC_BUF_ALIGN); | ||
358 | } else { | ||
359 | guard_width = | ||
360 | ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN); | ||
361 | guard_height = | ||
362 | ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN); | ||
363 | ctx->luma_size = ALIGN(guard_width * guard_height, | ||
364 | S5P_FIMV_DEC_BUF_ALIGN); | ||
365 | |||
366 | guard_width = | ||
367 | ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN); | ||
368 | guard_height = | ||
369 | ALIGN((ctx->img_height >> 1) + 4, | ||
370 | S5P_FIMV_NV12MT_VALIGN); | ||
371 | ctx->chroma_size = ALIGN(guard_width * guard_height, | ||
372 | S5P_FIMV_DEC_BUF_ALIGN); | ||
373 | |||
374 | ctx->mv_size = 0; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx) | ||
379 | { | ||
380 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) { | ||
381 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN); | ||
382 | |||
383 | ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN) | ||
384 | * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN); | ||
385 | ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN) | ||
386 | * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN); | ||
387 | |||
388 | ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN); | ||
389 | ctx->chroma_size = | ||
390 | ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN); | ||
391 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) { | ||
392 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN); | ||
393 | |||
394 | ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
395 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | ||
396 | ctx->chroma_size = | ||
397 | ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
398 | * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN); | ||
399 | |||
400 | ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN); | ||
401 | ctx->chroma_size = | ||
402 | ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* Set registers for decoding temporary buffers */ | ||
407 | static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx) | ||
408 | { | ||
409 | struct s5p_mfc_dev *dev = ctx->dev; | ||
410 | struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv; | ||
411 | |||
412 | mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR); | ||
413 | mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE); | ||
414 | } | ||
415 | |||
416 | /* Set registers for shared buffer */ | ||
417 | static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx) | ||
418 | { | ||
419 | struct s5p_mfc_dev *dev = ctx->dev; | ||
420 | mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR); | ||
421 | } | ||
422 | |||
423 | /* Set registers for decoding stream buffer */ | ||
424 | int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr, | ||
425 | unsigned int start_num_byte, unsigned int buf_size) | ||
426 | { | ||
427 | struct s5p_mfc_dev *dev = ctx->dev; | ||
428 | |||
429 | mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR); | ||
430 | mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE); | ||
431 | mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE); | ||
432 | s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | /* Set decoding frame buffer */ | ||
437 | int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx) | ||
438 | { | ||
439 | unsigned int frame_size, i; | ||
440 | unsigned int frame_size_ch, frame_size_mv; | ||
441 | struct s5p_mfc_dev *dev = ctx->dev; | ||
442 | unsigned int dpb; | ||
443 | size_t buf_addr1, buf_addr2; | ||
444 | int buf_size1, buf_size2; | ||
445 | |||
446 | buf_addr1 = ctx->bank1_phys; | ||
447 | buf_size1 = ctx->bank1_size; | ||
448 | buf_addr2 = ctx->bank2_phys; | ||
449 | buf_size2 = ctx->bank2_size; | ||
450 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & | ||
451 | ~S5P_FIMV_DPB_COUNT_MASK; | ||
452 | mfc_write(dev, ctx->total_dpb_count | dpb, | ||
453 | S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
454 | s5p_mfc_set_shared_buffer(ctx); | ||
455 | switch (ctx->codec_mode) { | ||
456 | case S5P_MFC_CODEC_H264_DEC: | ||
457 | mfc_write(dev, OFFSETA(buf_addr1), | ||
458 | S5P_FIMV_H264_VERT_NB_MV_ADR); | ||
459 | buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE; | ||
460 | buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE; | ||
461 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR); | ||
462 | buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE; | ||
463 | buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE; | ||
464 | break; | ||
465 | case S5P_MFC_CODEC_MPEG4_DEC: | ||
466 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR); | ||
467 | buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
468 | buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
469 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR); | ||
470 | buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
471 | buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
472 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR); | ||
473 | buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
474 | buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
475 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR); | ||
476 | buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE; | ||
477 | buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE; | ||
478 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR); | ||
479 | buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
480 | buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
481 | break; | ||
482 | case S5P_MFC_CODEC_H263_DEC: | ||
483 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR); | ||
484 | buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
485 | buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
486 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR); | ||
487 | buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
488 | buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
489 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR); | ||
490 | buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
491 | buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
492 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR); | ||
493 | buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
494 | buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
495 | break; | ||
496 | case S5P_MFC_CODEC_VC1_DEC: | ||
497 | case S5P_MFC_CODEC_VC1RCV_DEC: | ||
498 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR); | ||
499 | buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
500 | buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE; | ||
501 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR); | ||
502 | buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
503 | buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE; | ||
504 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR); | ||
505 | buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
506 | buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE; | ||
507 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR); | ||
508 | buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
509 | buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE; | ||
510 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR); | ||
511 | buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
512 | buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
513 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR); | ||
514 | buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
515 | buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
516 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR); | ||
517 | buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
518 | buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE; | ||
519 | break; | ||
520 | case S5P_MFC_CODEC_MPEG2_DEC: | ||
521 | break; | ||
522 | default: | ||
523 | mfc_err("Unknown codec for decoding (%x)\n", | ||
524 | ctx->codec_mode); | ||
525 | return -EINVAL; | ||
526 | break; | ||
527 | } | ||
528 | frame_size = ctx->luma_size; | ||
529 | frame_size_ch = ctx->chroma_size; | ||
530 | frame_size_mv = ctx->mv_size; | ||
531 | mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size, frame_size_ch, | ||
532 | frame_size_mv); | ||
533 | for (i = 0; i < ctx->total_dpb_count; i++) { | ||
534 | /* Bank2 */ | ||
535 | mfc_debug(2, "Luma %d: %x\n", i, | ||
536 | ctx->dst_bufs[i].cookie.raw.luma); | ||
537 | mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma), | ||
538 | S5P_FIMV_DEC_LUMA_ADR + i * 4); | ||
539 | mfc_debug(2, "\tChroma %d: %x\n", i, | ||
540 | ctx->dst_bufs[i].cookie.raw.chroma); | ||
541 | mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma), | ||
542 | S5P_FIMV_DEC_CHROMA_ADR + i * 4); | ||
543 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) { | ||
544 | mfc_debug(2, "\tBuf2: %x, size: %d\n", | ||
545 | buf_addr2, buf_size2); | ||
546 | mfc_write(dev, OFFSETB(buf_addr2), | ||
547 | S5P_FIMV_H264_MV_ADR + i * 4); | ||
548 | buf_addr2 += frame_size_mv; | ||
549 | buf_size2 -= frame_size_mv; | ||
550 | } | ||
551 | } | ||
552 | mfc_debug(2, "Buf1: %u, buf_size1: %d\n", buf_addr1, buf_size1); | ||
553 | mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n", | ||
554 | buf_size1, buf_size2, ctx->total_dpb_count); | ||
555 | if (buf_size1 < 0 || buf_size2 < 0) { | ||
556 | mfc_debug(2, "Not enough memory has been allocated\n"); | ||
557 | return -ENOMEM; | ||
558 | } | ||
559 | s5p_mfc_write_info_v5(ctx, frame_size, ALLOC_LUMA_DPB_SIZE); | ||
560 | s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE); | ||
561 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) | ||
562 | s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE); | ||
563 | mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK) | ||
564 | << S5P_FIMV_CH_SHIFT) | (ctx->inst_no), | ||
565 | S5P_FIMV_SI_CH0_INST_ID); | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | /* Set registers for encoding stream buffer */ | ||
570 | int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx, | ||
571 | unsigned long addr, unsigned int size) | ||
572 | { | ||
573 | struct s5p_mfc_dev *dev = ctx->dev; | ||
574 | |||
575 | mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR); | ||
576 | mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE); | ||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, | ||
581 | unsigned long y_addr, unsigned long c_addr) | ||
582 | { | ||
583 | struct s5p_mfc_dev *dev = ctx->dev; | ||
584 | |||
585 | mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR); | ||
586 | mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR); | ||
587 | } | ||
588 | |||
589 | void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, | ||
590 | unsigned long *y_addr, unsigned long *c_addr) | ||
591 | { | ||
592 | struct s5p_mfc_dev *dev = ctx->dev; | ||
593 | |||
594 | *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) | ||
595 | << MFC_OFFSET_SHIFT); | ||
596 | *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) | ||
597 | << MFC_OFFSET_SHIFT); | ||
598 | } | ||
599 | |||
600 | /* Set encoding ref & codec buffer */ | ||
601 | int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx) | ||
602 | { | ||
603 | struct s5p_mfc_dev *dev = ctx->dev; | ||
604 | size_t buf_addr1, buf_addr2; | ||
605 | size_t buf_size1, buf_size2; | ||
606 | unsigned int enc_ref_y_size, enc_ref_c_size; | ||
607 | unsigned int guard_width, guard_height; | ||
608 | int i; | ||
609 | |||
610 | buf_addr1 = ctx->bank1_phys; | ||
611 | buf_size1 = ctx->bank1_size; | ||
612 | buf_addr2 = ctx->bank2_phys; | ||
613 | buf_size2 = ctx->bank2_size; | ||
614 | enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
615 | * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN); | ||
616 | enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN); | ||
617 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) { | ||
618 | enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN) | ||
619 | * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN); | ||
620 | enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN); | ||
621 | } else { | ||
622 | guard_width = ALIGN(ctx->img_width + 16, | ||
623 | S5P_FIMV_NV12MT_HALIGN); | ||
624 | guard_height = ALIGN((ctx->img_height >> 1) + 4, | ||
625 | S5P_FIMV_NV12MT_VALIGN); | ||
626 | enc_ref_c_size = ALIGN(guard_width * guard_height, | ||
627 | S5P_FIMV_NV12MT_SALIGN); | ||
628 | } | ||
629 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", buf_size1, buf_size2); | ||
630 | switch (ctx->codec_mode) { | ||
631 | case S5P_MFC_CODEC_H264_ENC: | ||
632 | for (i = 0; i < 2; i++) { | ||
633 | mfc_write(dev, OFFSETA(buf_addr1), | ||
634 | S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i)); | ||
635 | buf_addr1 += enc_ref_y_size; | ||
636 | buf_size1 -= enc_ref_y_size; | ||
637 | |||
638 | mfc_write(dev, OFFSETB(buf_addr2), | ||
639 | S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i)); | ||
640 | buf_addr2 += enc_ref_y_size; | ||
641 | buf_size2 -= enc_ref_y_size; | ||
642 | } | ||
643 | for (i = 0; i < 4; i++) { | ||
644 | mfc_write(dev, OFFSETB(buf_addr2), | ||
645 | S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i)); | ||
646 | buf_addr2 += enc_ref_c_size; | ||
647 | buf_size2 -= enc_ref_c_size; | ||
648 | } | ||
649 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR); | ||
650 | buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE; | ||
651 | buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE; | ||
652 | mfc_write(dev, OFFSETA(buf_addr1), | ||
653 | S5P_FIMV_H264_COZERO_FLAG_ADR); | ||
654 | buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE; | ||
655 | buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE; | ||
656 | mfc_write(dev, OFFSETA(buf_addr1), | ||
657 | S5P_FIMV_H264_UP_INTRA_MD_ADR); | ||
658 | buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE; | ||
659 | buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE; | ||
660 | mfc_write(dev, OFFSETB(buf_addr2), | ||
661 | S5P_FIMV_H264_UP_INTRA_PRED_ADR); | ||
662 | buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE; | ||
663 | buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE; | ||
664 | mfc_write(dev, OFFSETA(buf_addr1), | ||
665 | S5P_FIMV_H264_NBOR_INFO_ADR); | ||
666 | buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE; | ||
667 | buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE; | ||
668 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", | ||
669 | buf_size1, buf_size2); | ||
670 | break; | ||
671 | case S5P_MFC_CODEC_MPEG4_ENC: | ||
672 | for (i = 0; i < 2; i++) { | ||
673 | mfc_write(dev, OFFSETA(buf_addr1), | ||
674 | S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i)); | ||
675 | buf_addr1 += enc_ref_y_size; | ||
676 | buf_size1 -= enc_ref_y_size; | ||
677 | mfc_write(dev, OFFSETB(buf_addr2), | ||
678 | S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i)); | ||
679 | buf_addr2 += enc_ref_y_size; | ||
680 | buf_size2 -= enc_ref_y_size; | ||
681 | } | ||
682 | for (i = 0; i < 4; i++) { | ||
683 | mfc_write(dev, OFFSETB(buf_addr2), | ||
684 | S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i)); | ||
685 | buf_addr2 += enc_ref_c_size; | ||
686 | buf_size2 -= enc_ref_c_size; | ||
687 | } | ||
688 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR); | ||
689 | buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE; | ||
690 | buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE; | ||
691 | mfc_write(dev, OFFSETA(buf_addr1), | ||
692 | S5P_FIMV_MPEG4_COZERO_FLAG_ADR); | ||
693 | buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE; | ||
694 | buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE; | ||
695 | mfc_write(dev, OFFSETA(buf_addr1), | ||
696 | S5P_FIMV_MPEG4_ACDC_COEF_ADR); | ||
697 | buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
698 | buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
699 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", | ||
700 | buf_size1, buf_size2); | ||
701 | break; | ||
702 | case S5P_MFC_CODEC_H263_ENC: | ||
703 | for (i = 0; i < 2; i++) { | ||
704 | mfc_write(dev, OFFSETA(buf_addr1), | ||
705 | S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i)); | ||
706 | buf_addr1 += enc_ref_y_size; | ||
707 | buf_size1 -= enc_ref_y_size; | ||
708 | mfc_write(dev, OFFSETB(buf_addr2), | ||
709 | S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i)); | ||
710 | buf_addr2 += enc_ref_y_size; | ||
711 | buf_size2 -= enc_ref_y_size; | ||
712 | } | ||
713 | for (i = 0; i < 4; i++) { | ||
714 | mfc_write(dev, OFFSETB(buf_addr2), | ||
715 | S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i)); | ||
716 | buf_addr2 += enc_ref_c_size; | ||
717 | buf_size2 -= enc_ref_c_size; | ||
718 | } | ||
719 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR); | ||
720 | buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE; | ||
721 | buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE; | ||
722 | mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR); | ||
723 | buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
724 | buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE; | ||
725 | mfc_debug(2, "buf_size1: %d, buf_size2: %d\n", | ||
726 | buf_size1, buf_size2); | ||
727 | break; | ||
728 | default: | ||
729 | mfc_err("Unknown codec set for encoding: %d\n", | ||
730 | ctx->codec_mode); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) | ||
737 | { | ||
738 | struct s5p_mfc_dev *dev = ctx->dev; | ||
739 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
740 | unsigned int reg; | ||
741 | unsigned int shm; | ||
742 | |||
743 | /* width */ | ||
744 | mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX); | ||
745 | /* height */ | ||
746 | mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX); | ||
747 | /* pictype : enable, IDR period */ | ||
748 | reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
749 | reg |= (1 << 18); | ||
750 | reg &= ~(0xFFFF); | ||
751 | reg |= p->gop_size; | ||
752 | mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
753 | mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON); | ||
754 | /* multi-slice control */ | ||
755 | /* multi-slice MB number or bit size */ | ||
756 | mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL); | ||
757 | if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { | ||
758 | mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB); | ||
759 | } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { | ||
760 | mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT); | ||
761 | } else { | ||
762 | mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB); | ||
763 | mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT); | ||
764 | } | ||
765 | /* cyclic intra refresh */ | ||
766 | mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL); | ||
767 | /* memory structure cur. frame */ | ||
768 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) | ||
769 | mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
770 | else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) | ||
771 | mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
772 | /* padding control & value */ | ||
773 | reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL); | ||
774 | if (p->pad) { | ||
775 | /** enable */ | ||
776 | reg |= (1 << 31); | ||
777 | /** cr value */ | ||
778 | reg &= ~(0xFF << 16); | ||
779 | reg |= (p->pad_cr << 16); | ||
780 | /** cb value */ | ||
781 | reg &= ~(0xFF << 8); | ||
782 | reg |= (p->pad_cb << 8); | ||
783 | /** y value */ | ||
784 | reg &= ~(0xFF); | ||
785 | reg |= (p->pad_luma); | ||
786 | } else { | ||
787 | /** disable & all value clear */ | ||
788 | reg = 0; | ||
789 | } | ||
790 | mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL); | ||
791 | /* rate control config. */ | ||
792 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
793 | /** frame-level rate control */ | ||
794 | reg &= ~(0x1 << 9); | ||
795 | reg |= (p->rc_frame << 9); | ||
796 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
797 | /* bit rate */ | ||
798 | if (p->rc_frame) | ||
799 | mfc_write(dev, p->rc_bitrate, | ||
800 | S5P_FIMV_ENC_RC_BIT_RATE); | ||
801 | else | ||
802 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE); | ||
803 | /* reaction coefficient */ | ||
804 | if (p->rc_frame) | ||
805 | mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA); | ||
806 | shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL); | ||
807 | /* seq header ctrl */ | ||
808 | shm &= ~(0x1 << 3); | ||
809 | shm |= (p->seq_hdr_mode << 3); | ||
810 | /* frame skip mode */ | ||
811 | shm &= ~(0x3 << 1); | ||
812 | shm |= (p->frame_skip_mode << 1); | ||
813 | s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL); | ||
814 | /* fixed target bit */ | ||
815 | s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG); | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) | ||
820 | { | ||
821 | struct s5p_mfc_dev *dev = ctx->dev; | ||
822 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
823 | struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264; | ||
824 | unsigned int reg; | ||
825 | unsigned int shm; | ||
826 | |||
827 | s5p_mfc_set_enc_params(ctx); | ||
828 | /* pictype : number of B */ | ||
829 | reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
830 | /* num_b_frame - 0 ~ 2 */ | ||
831 | reg &= ~(0x3 << 16); | ||
832 | reg |= (p->num_b_frame << 16); | ||
833 | mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
834 | /* profile & level */ | ||
835 | reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE); | ||
836 | /* level */ | ||
837 | reg &= ~(0xFF << 8); | ||
838 | reg |= (p_264->level << 8); | ||
839 | /* profile - 0 ~ 2 */ | ||
840 | reg &= ~(0x3F); | ||
841 | reg |= p_264->profile; | ||
842 | mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE); | ||
843 | /* interlace */ | ||
844 | mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT); | ||
845 | /* height */ | ||
846 | if (p_264->interlace) | ||
847 | mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX); | ||
848 | /* loopfilter ctrl */ | ||
849 | mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL); | ||
850 | /* loopfilter alpha offset */ | ||
851 | if (p_264->loop_filter_alpha < 0) { | ||
852 | reg = 0x10; | ||
853 | reg |= (0xFF - p_264->loop_filter_alpha) + 1; | ||
854 | } else { | ||
855 | reg = 0x00; | ||
856 | reg |= (p_264->loop_filter_alpha & 0xF); | ||
857 | } | ||
858 | mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF); | ||
859 | /* loopfilter beta offset */ | ||
860 | if (p_264->loop_filter_beta < 0) { | ||
861 | reg = 0x10; | ||
862 | reg |= (0xFF - p_264->loop_filter_beta) + 1; | ||
863 | } else { | ||
864 | reg = 0x00; | ||
865 | reg |= (p_264->loop_filter_beta & 0xF); | ||
866 | } | ||
867 | mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF); | ||
868 | /* entropy coding mode */ | ||
869 | if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) | ||
870 | mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE); | ||
871 | else | ||
872 | mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE); | ||
873 | /* number of ref. picture */ | ||
874 | reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF); | ||
875 | /* num of ref. pictures of P */ | ||
876 | reg &= ~(0x3 << 5); | ||
877 | reg |= (p_264->num_ref_pic_4p << 5); | ||
878 | /* max number of ref. pictures */ | ||
879 | reg &= ~(0x1F); | ||
880 | reg |= p_264->max_ref_pic; | ||
881 | mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF); | ||
882 | /* 8x8 transform enable */ | ||
883 | mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG); | ||
884 | /* rate control config. */ | ||
885 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
886 | /* macroblock level rate control */ | ||
887 | reg &= ~(0x1 << 8); | ||
888 | reg |= (p->rc_mb << 8); | ||
889 | /* frame QP */ | ||
890 | reg &= ~(0x3F); | ||
891 | reg |= p_264->rc_frame_qp; | ||
892 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
893 | /* frame rate */ | ||
894 | if (p->rc_frame && p->rc_framerate_denom) | ||
895 | mfc_write(dev, p->rc_framerate_num * 1000 | ||
896 | / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
897 | else | ||
898 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
899 | /* max & min value of QP */ | ||
900 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND); | ||
901 | /* max QP */ | ||
902 | reg &= ~(0x3F << 8); | ||
903 | reg |= (p_264->rc_max_qp << 8); | ||
904 | /* min QP */ | ||
905 | reg &= ~(0x3F); | ||
906 | reg |= p_264->rc_min_qp; | ||
907 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND); | ||
908 | /* macroblock adaptive scaling features */ | ||
909 | if (p->rc_mb) { | ||
910 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL); | ||
911 | /* dark region */ | ||
912 | reg &= ~(0x1 << 3); | ||
913 | reg |= (p_264->rc_mb_dark << 3); | ||
914 | /* smooth region */ | ||
915 | reg &= ~(0x1 << 2); | ||
916 | reg |= (p_264->rc_mb_smooth << 2); | ||
917 | /* static region */ | ||
918 | reg &= ~(0x1 << 1); | ||
919 | reg |= (p_264->rc_mb_static << 1); | ||
920 | /* high activity region */ | ||
921 | reg &= ~(0x1); | ||
922 | reg |= p_264->rc_mb_activity; | ||
923 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL); | ||
924 | } | ||
925 | if (!p->rc_frame && !p->rc_mb) { | ||
926 | shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP); | ||
927 | shm &= ~(0xFFF); | ||
928 | shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6); | ||
929 | shm |= (p_264->rc_p_frame_qp & 0x3F); | ||
930 | s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP); | ||
931 | } | ||
932 | /* extended encoder ctrl */ | ||
933 | shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL); | ||
934 | /* AR VUI control */ | ||
935 | shm &= ~(0x1 << 15); | ||
936 | shm |= (p_264->vui_sar << 1); | ||
937 | s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL); | ||
938 | if (p_264->vui_sar) { | ||
939 | /* aspect ration IDC */ | ||
940 | shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC); | ||
941 | shm &= ~(0xFF); | ||
942 | shm |= p_264->vui_sar_idc; | ||
943 | s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC); | ||
944 | if (p_264->vui_sar_idc == 0xFF) { | ||
945 | /* sample AR info */ | ||
946 | shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR); | ||
947 | shm &= ~(0xFFFFFFFF); | ||
948 | shm |= p_264->vui_ext_sar_width << 16; | ||
949 | shm |= p_264->vui_ext_sar_height; | ||
950 | s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR); | ||
951 | } | ||
952 | } | ||
953 | /* intra picture period for H.264 */ | ||
954 | shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD); | ||
955 | /* control */ | ||
956 | shm &= ~(0x1 << 16); | ||
957 | shm |= (p_264->open_gop << 16); | ||
958 | /* value */ | ||
959 | if (p_264->open_gop) { | ||
960 | shm &= ~(0xFFFF); | ||
961 | shm |= p_264->open_gop_size; | ||
962 | } | ||
963 | s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD); | ||
964 | /* extended encoder ctrl */ | ||
965 | shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL); | ||
966 | /* vbv buffer size */ | ||
967 | if (p->frame_skip_mode == | ||
968 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
969 | shm &= ~(0xFFFF << 16); | ||
970 | shm |= (p_264->cpb_size << 16); | ||
971 | } | ||
972 | s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL); | ||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) | ||
977 | { | ||
978 | struct s5p_mfc_dev *dev = ctx->dev; | ||
979 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
980 | struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4; | ||
981 | unsigned int reg; | ||
982 | unsigned int shm; | ||
983 | unsigned int framerate; | ||
984 | |||
985 | s5p_mfc_set_enc_params(ctx); | ||
986 | /* pictype : number of B */ | ||
987 | reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
988 | /* num_b_frame - 0 ~ 2 */ | ||
989 | reg &= ~(0x3 << 16); | ||
990 | reg |= (p->num_b_frame << 16); | ||
991 | mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL); | ||
992 | /* profile & level */ | ||
993 | reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE); | ||
994 | /* level */ | ||
995 | reg &= ~(0xFF << 8); | ||
996 | reg |= (p_mpeg4->level << 8); | ||
997 | /* profile - 0 ~ 2 */ | ||
998 | reg &= ~(0x3F); | ||
999 | reg |= p_mpeg4->profile; | ||
1000 | mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE); | ||
1001 | /* quarter_pixel */ | ||
1002 | mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL); | ||
1003 | /* qp */ | ||
1004 | if (!p->rc_frame) { | ||
1005 | shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP); | ||
1006 | shm &= ~(0xFFF); | ||
1007 | shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6); | ||
1008 | shm |= (p_mpeg4->rc_p_frame_qp & 0x3F); | ||
1009 | s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP); | ||
1010 | } | ||
1011 | /* frame rate */ | ||
1012 | if (p->rc_frame) { | ||
1013 | if (p->rc_framerate_denom > 0) { | ||
1014 | framerate = p->rc_framerate_num * 1000 / | ||
1015 | p->rc_framerate_denom; | ||
1016 | mfc_write(dev, framerate, | ||
1017 | S5P_FIMV_ENC_RC_FRAME_RATE); | ||
1018 | shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING); | ||
1019 | shm &= ~(0xFFFFFFFF); | ||
1020 | shm |= (1 << 31); | ||
1021 | shm |= ((p->rc_framerate_num & 0x7FFF) << 16); | ||
1022 | shm |= (p->rc_framerate_denom & 0xFFFF); | ||
1023 | s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING); | ||
1024 | } | ||
1025 | } else { | ||
1026 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
1027 | } | ||
1028 | /* rate control config. */ | ||
1029 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
1030 | /* frame QP */ | ||
1031 | reg &= ~(0x3F); | ||
1032 | reg |= p_mpeg4->rc_frame_qp; | ||
1033 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
1034 | /* max & min value of QP */ | ||
1035 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND); | ||
1036 | /* max QP */ | ||
1037 | reg &= ~(0x3F << 8); | ||
1038 | reg |= (p_mpeg4->rc_max_qp << 8); | ||
1039 | /* min QP */ | ||
1040 | reg &= ~(0x3F); | ||
1041 | reg |= p_mpeg4->rc_min_qp; | ||
1042 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND); | ||
1043 | /* extended encoder ctrl */ | ||
1044 | shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL); | ||
1045 | /* vbv buffer size */ | ||
1046 | if (p->frame_skip_mode == | ||
1047 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
1048 | shm &= ~(0xFFFF << 16); | ||
1049 | shm |= (p->vbv_size << 16); | ||
1050 | } | ||
1051 | s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL); | ||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
1055 | static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) | ||
1056 | { | ||
1057 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1058 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
1059 | struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4; | ||
1060 | unsigned int reg; | ||
1061 | unsigned int shm; | ||
1062 | |||
1063 | s5p_mfc_set_enc_params(ctx); | ||
1064 | /* qp */ | ||
1065 | if (!p->rc_frame) { | ||
1066 | shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP); | ||
1067 | shm &= ~(0xFFF); | ||
1068 | shm |= (p_h263->rc_p_frame_qp & 0x3F); | ||
1069 | s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP); | ||
1070 | } | ||
1071 | /* frame rate */ | ||
1072 | if (p->rc_frame && p->rc_framerate_denom) | ||
1073 | mfc_write(dev, p->rc_framerate_num * 1000 | ||
1074 | / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
1075 | else | ||
1076 | mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE); | ||
1077 | /* rate control config. */ | ||
1078 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG); | ||
1079 | /* frame QP */ | ||
1080 | reg &= ~(0x3F); | ||
1081 | reg |= p_h263->rc_frame_qp; | ||
1082 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG); | ||
1083 | /* max & min value of QP */ | ||
1084 | reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND); | ||
1085 | /* max QP */ | ||
1086 | reg &= ~(0x3F << 8); | ||
1087 | reg |= (p_h263->rc_max_qp << 8); | ||
1088 | /* min QP */ | ||
1089 | reg &= ~(0x3F); | ||
1090 | reg |= p_h263->rc_min_qp; | ||
1091 | mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND); | ||
1092 | /* extended encoder ctrl */ | ||
1093 | shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL); | ||
1094 | /* vbv buffer size */ | ||
1095 | if (p->frame_skip_mode == | ||
1096 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
1097 | shm &= ~(0xFFFF << 16); | ||
1098 | shm |= (p->vbv_size << 16); | ||
1099 | } | ||
1100 | s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL); | ||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | /* Initialize decoding */ | ||
1105 | int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx) | ||
1106 | { | ||
1107 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1108 | |||
1109 | s5p_mfc_set_shared_buffer(ctx); | ||
1110 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ | ||
1111 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) | ||
1112 | mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL); | ||
1113 | else | ||
1114 | mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL); | ||
1115 | mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) << | ||
1116 | S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable << | ||
1117 | S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay & | ||
1118 | S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT), | ||
1119 | S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
1120 | mfc_write(dev, | ||
1121 | ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | ||
1122 | | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1126 | static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) | ||
1127 | { | ||
1128 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1129 | unsigned int dpb; | ||
1130 | |||
1131 | if (flush) | ||
1132 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | ( | ||
1133 | S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT); | ||
1134 | else | ||
1135 | dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & | ||
1136 | ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT); | ||
1137 | mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
1138 | } | ||
1139 | |||
1140 | /* Decode a single frame */ | ||
1141 | int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx, | ||
1142 | enum s5p_mfc_decode_arg last_frame) | ||
1143 | { | ||
1144 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1145 | |||
1146 | mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF); | ||
1147 | s5p_mfc_set_shared_buffer(ctx); | ||
1148 | s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag); | ||
1149 | /* Issue different commands to instance basing on whether it | ||
1150 | * is the last frame or not. */ | ||
1151 | switch (last_frame) { | ||
1152 | case MFC_DEC_FRAME: | ||
1153 | mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) << | ||
1154 | S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1155 | break; | ||
1156 | case MFC_DEC_LAST_FRAME: | ||
1157 | mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) << | ||
1158 | S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1159 | break; | ||
1160 | case MFC_DEC_RES_CHANGE: | ||
1161 | mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC & | ||
1162 | S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no), | ||
1163 | S5P_FIMV_SI_CH0_INST_ID); | ||
1164 | break; | ||
1165 | } | ||
1166 | mfc_debug(2, "Decoding a usual frame\n"); | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx) | ||
1171 | { | ||
1172 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1173 | |||
1174 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | ||
1175 | s5p_mfc_set_enc_params_h264(ctx); | ||
1176 | else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC) | ||
1177 | s5p_mfc_set_enc_params_mpeg4(ctx); | ||
1178 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) | ||
1179 | s5p_mfc_set_enc_params_h263(ctx); | ||
1180 | else { | ||
1181 | mfc_err("Unknown codec for encoding (%x)\n", | ||
1182 | ctx->codec_mode); | ||
1183 | return -EINVAL; | ||
1184 | } | ||
1185 | s5p_mfc_set_shared_buffer(ctx); | ||
1186 | mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) | | ||
1187 | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1188 | return 0; | ||
1189 | } | ||
1190 | |||
1191 | /* Encode a single frame */ | ||
1192 | int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx) | ||
1193 | { | ||
1194 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1195 | int cmd; | ||
1196 | /* memory structure cur. frame */ | ||
1197 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) | ||
1198 | mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
1199 | else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) | ||
1200 | mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); | ||
1201 | s5p_mfc_set_shared_buffer(ctx); | ||
1202 | |||
1203 | if (ctx->state == MFCINST_FINISHING) | ||
1204 | cmd = S5P_FIMV_CH_LAST_FRAME; | ||
1205 | else | ||
1206 | cmd = S5P_FIMV_CH_FRAME_START; | ||
1207 | mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | ||
1208 | | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); | ||
1209 | |||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | static int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) | ||
1214 | { | ||
1215 | unsigned long flags; | ||
1216 | int new_ctx; | ||
1217 | int cnt; | ||
1218 | |||
1219 | spin_lock_irqsave(&dev->condlock, flags); | ||
1220 | new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; | ||
1221 | cnt = 0; | ||
1222 | while (!test_bit(new_ctx, &dev->ctx_work_bits)) { | ||
1223 | new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS; | ||
1224 | if (++cnt > MFC_NUM_CONTEXTS) { | ||
1225 | /* No contexts to run */ | ||
1226 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
1227 | return -EAGAIN; | ||
1228 | } | ||
1229 | } | ||
1230 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
1231 | return new_ctx; | ||
1232 | } | ||
1233 | |||
1234 | static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx) | ||
1235 | { | ||
1236 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1237 | |||
1238 | s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0); | ||
1239 | dev->curr_ctx = ctx->num; | ||
1240 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1241 | s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE); | ||
1242 | } | ||
1243 | |||
1244 | static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) | ||
1245 | { | ||
1246 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1247 | struct s5p_mfc_buf *temp_vb; | ||
1248 | unsigned long flags; | ||
1249 | unsigned int index; | ||
1250 | |||
1251 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1252 | /* Frames are being decoded */ | ||
1253 | if (list_empty(&ctx->src_queue)) { | ||
1254 | mfc_debug(2, "No src buffers\n"); | ||
1255 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1256 | return -EAGAIN; | ||
1257 | } | ||
1258 | /* Get the next source buffer */ | ||
1259 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1260 | temp_vb->flags |= MFC_BUF_FLAG_USED; | ||
1261 | s5p_mfc_set_dec_stream_buffer_v5(ctx, | ||
1262 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | ||
1263 | ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused); | ||
1264 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1265 | index = temp_vb->b->v4l2_buf.index; | ||
1266 | dev->curr_ctx = ctx->num; | ||
1267 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1268 | if (temp_vb->b->v4l2_planes[0].bytesused == 0) { | ||
1269 | last_frame = MFC_DEC_LAST_FRAME; | ||
1270 | mfc_debug(2, "Setting ctx->state to FINISHING\n"); | ||
1271 | ctx->state = MFCINST_FINISHING; | ||
1272 | } | ||
1273 | s5p_mfc_decode_one_frame_v5(ctx, last_frame); | ||
1274 | return 0; | ||
1275 | } | ||
1276 | |||
1277 | static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | ||
1278 | { | ||
1279 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1280 | unsigned long flags; | ||
1281 | struct s5p_mfc_buf *dst_mb; | ||
1282 | struct s5p_mfc_buf *src_mb; | ||
1283 | unsigned long src_y_addr, src_c_addr, dst_addr; | ||
1284 | unsigned int dst_size; | ||
1285 | |||
1286 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1287 | if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) { | ||
1288 | mfc_debug(2, "no src buffers\n"); | ||
1289 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1290 | return -EAGAIN; | ||
1291 | } | ||
1292 | if (list_empty(&ctx->dst_queue)) { | ||
1293 | mfc_debug(2, "no dst buffers\n"); | ||
1294 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1295 | return -EAGAIN; | ||
1296 | } | ||
1297 | if (list_empty(&ctx->src_queue)) { | ||
1298 | /* send null frame */ | ||
1299 | s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, dev->bank2); | ||
1300 | src_mb = NULL; | ||
1301 | } else { | ||
1302 | src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, | ||
1303 | list); | ||
1304 | src_mb->flags |= MFC_BUF_FLAG_USED; | ||
1305 | if (src_mb->b->v4l2_planes[0].bytesused == 0) { | ||
1306 | /* send null frame */ | ||
1307 | s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, | ||
1308 | dev->bank2); | ||
1309 | ctx->state = MFCINST_FINISHING; | ||
1310 | } else { | ||
1311 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, | ||
1312 | 0); | ||
1313 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, | ||
1314 | 1); | ||
1315 | s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr, | ||
1316 | src_c_addr); | ||
1317 | if (src_mb->flags & MFC_BUF_FLAG_EOS) | ||
1318 | ctx->state = MFCINST_FINISHING; | ||
1319 | } | ||
1320 | } | ||
1321 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | ||
1322 | dst_mb->flags |= MFC_BUF_FLAG_USED; | ||
1323 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | ||
1324 | dst_size = vb2_plane_size(dst_mb->b, 0); | ||
1325 | s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size); | ||
1326 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1327 | dev->curr_ctx = ctx->num; | ||
1328 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1329 | mfc_debug(2, "encoding buffer with index=%d state=%d", | ||
1330 | src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); | ||
1331 | s5p_mfc_encode_one_frame_v5(ctx); | ||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) | ||
1336 | { | ||
1337 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1338 | unsigned long flags; | ||
1339 | struct s5p_mfc_buf *temp_vb; | ||
1340 | |||
1341 | /* Initializing decoding - parsing header */ | ||
1342 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1343 | mfc_debug(2, "Preparing to init decoding\n"); | ||
1344 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1345 | s5p_mfc_set_dec_desc_buffer(ctx); | ||
1346 | mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); | ||
1347 | s5p_mfc_set_dec_stream_buffer_v5(ctx, | ||
1348 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | ||
1349 | 0, temp_vb->b->v4l2_planes[0].bytesused); | ||
1350 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1351 | dev->curr_ctx = ctx->num; | ||
1352 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1353 | s5p_mfc_init_decode_v5(ctx); | ||
1354 | } | ||
1355 | |||
1356 | static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) | ||
1357 | { | ||
1358 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1359 | unsigned long flags; | ||
1360 | struct s5p_mfc_buf *dst_mb; | ||
1361 | unsigned long dst_addr; | ||
1362 | unsigned int dst_size; | ||
1363 | |||
1364 | s5p_mfc_set_enc_ref_buffer_v5(ctx); | ||
1365 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1366 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | ||
1367 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | ||
1368 | dst_size = vb2_plane_size(dst_mb->b, 0); | ||
1369 | s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size); | ||
1370 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1371 | dev->curr_ctx = ctx->num; | ||
1372 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1373 | s5p_mfc_init_encode_v5(ctx); | ||
1374 | } | ||
1375 | |||
1376 | static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) | ||
1377 | { | ||
1378 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1379 | unsigned long flags; | ||
1380 | struct s5p_mfc_buf *temp_vb; | ||
1381 | int ret; | ||
1382 | |||
1383 | /* | ||
1384 | * Header was parsed now starting processing | ||
1385 | * First set the output frame buffers | ||
1386 | */ | ||
1387 | if (ctx->capture_state != QUEUE_BUFS_MMAPED) { | ||
1388 | mfc_err("It seems that not all destionation buffers were " | ||
1389 | "mmaped\nMFC requires that all destination are mmaped " | ||
1390 | "before starting processing\n"); | ||
1391 | return -EAGAIN; | ||
1392 | } | ||
1393 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1394 | if (list_empty(&ctx->src_queue)) { | ||
1395 | mfc_err("Header has been deallocated in the middle of" | ||
1396 | " initialization\n"); | ||
1397 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1398 | return -EIO; | ||
1399 | } | ||
1400 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1401 | mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); | ||
1402 | s5p_mfc_set_dec_stream_buffer_v5(ctx, | ||
1403 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | ||
1404 | 0, temp_vb->b->v4l2_planes[0].bytesused); | ||
1405 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1406 | dev->curr_ctx = ctx->num; | ||
1407 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1408 | ret = s5p_mfc_set_dec_frame_buffer_v5(ctx); | ||
1409 | if (ret) { | ||
1410 | mfc_err("Failed to alloc frame mem\n"); | ||
1411 | ctx->state = MFCINST_ERROR; | ||
1412 | } | ||
1413 | return ret; | ||
1414 | } | ||
1415 | |||
1416 | /* Try running an operation on hardware */ | ||
1417 | void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) | ||
1418 | { | ||
1419 | struct s5p_mfc_ctx *ctx; | ||
1420 | int new_ctx; | ||
1421 | unsigned int ret = 0; | ||
1422 | |||
1423 | if (test_bit(0, &dev->enter_suspend)) { | ||
1424 | mfc_debug(1, "Entering suspend so do not schedule any jobs\n"); | ||
1425 | return; | ||
1426 | } | ||
1427 | /* Check whether hardware is not running */ | ||
1428 | if (test_and_set_bit(0, &dev->hw_lock) != 0) { | ||
1429 | /* This is perfectly ok, the scheduled ctx should wait */ | ||
1430 | mfc_debug(1, "Couldn't lock HW\n"); | ||
1431 | return; | ||
1432 | } | ||
1433 | /* Choose the context to run */ | ||
1434 | new_ctx = s5p_mfc_get_new_ctx(dev); | ||
1435 | if (new_ctx < 0) { | ||
1436 | /* No contexts to run */ | ||
1437 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) { | ||
1438 | mfc_err("Failed to unlock hardware\n"); | ||
1439 | return; | ||
1440 | } | ||
1441 | mfc_debug(1, "No ctx is scheduled to be run\n"); | ||
1442 | return; | ||
1443 | } | ||
1444 | ctx = dev->ctx[new_ctx]; | ||
1445 | /* Got context to run in ctx */ | ||
1446 | /* | ||
1447 | * Last frame has already been sent to MFC. | ||
1448 | * Now obtaining frames from MFC buffer | ||
1449 | */ | ||
1450 | s5p_mfc_clock_on(); | ||
1451 | if (ctx->type == MFCINST_DECODER) { | ||
1452 | s5p_mfc_set_dec_desc_buffer(ctx); | ||
1453 | switch (ctx->state) { | ||
1454 | case MFCINST_FINISHING: | ||
1455 | s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME); | ||
1456 | break; | ||
1457 | case MFCINST_RUNNING: | ||
1458 | ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME); | ||
1459 | break; | ||
1460 | case MFCINST_INIT: | ||
1461 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1462 | ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, | ||
1463 | ctx); | ||
1464 | break; | ||
1465 | case MFCINST_RETURN_INST: | ||
1466 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1467 | ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, | ||
1468 | ctx); | ||
1469 | break; | ||
1470 | case MFCINST_GOT_INST: | ||
1471 | s5p_mfc_run_init_dec(ctx); | ||
1472 | break; | ||
1473 | case MFCINST_HEAD_PARSED: | ||
1474 | ret = s5p_mfc_run_init_dec_buffers(ctx); | ||
1475 | mfc_debug(1, "head parsed\n"); | ||
1476 | break; | ||
1477 | case MFCINST_RES_CHANGE_INIT: | ||
1478 | s5p_mfc_run_res_change(ctx); | ||
1479 | break; | ||
1480 | case MFCINST_RES_CHANGE_FLUSH: | ||
1481 | s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME); | ||
1482 | break; | ||
1483 | case MFCINST_RES_CHANGE_END: | ||
1484 | mfc_debug(2, "Finished remaining frames after resolution change\n"); | ||
1485 | ctx->capture_state = QUEUE_FREE; | ||
1486 | mfc_debug(2, "Will re-init the codec\n"); | ||
1487 | s5p_mfc_run_init_dec(ctx); | ||
1488 | break; | ||
1489 | default: | ||
1490 | ret = -EAGAIN; | ||
1491 | } | ||
1492 | } else if (ctx->type == MFCINST_ENCODER) { | ||
1493 | switch (ctx->state) { | ||
1494 | case MFCINST_FINISHING: | ||
1495 | case MFCINST_RUNNING: | ||
1496 | ret = s5p_mfc_run_enc_frame(ctx); | ||
1497 | break; | ||
1498 | case MFCINST_INIT: | ||
1499 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1500 | ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, | ||
1501 | ctx); | ||
1502 | break; | ||
1503 | case MFCINST_RETURN_INST: | ||
1504 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1505 | ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, | ||
1506 | ctx); | ||
1507 | break; | ||
1508 | case MFCINST_GOT_INST: | ||
1509 | s5p_mfc_run_init_enc(ctx); | ||
1510 | break; | ||
1511 | default: | ||
1512 | ret = -EAGAIN; | ||
1513 | } | ||
1514 | } else { | ||
1515 | mfc_err("Invalid context type: %d\n", ctx->type); | ||
1516 | ret = -EAGAIN; | ||
1517 | } | ||
1518 | |||
1519 | if (ret) { | ||
1520 | /* Free hardware lock */ | ||
1521 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
1522 | mfc_err("Failed to unlock hardware\n"); | ||
1523 | |||
1524 | /* This is in deed imporant, as no operation has been | ||
1525 | * scheduled, reduce the clock count as no one will | ||
1526 | * ever do this, because no interrupt related to this try_run | ||
1527 | * will ever come from hardware. */ | ||
1528 | s5p_mfc_clock_off(); | ||
1529 | } | ||
1530 | } | ||
1531 | |||
1532 | |||
1533 | void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq) | ||
1534 | { | ||
1535 | struct s5p_mfc_buf *b; | ||
1536 | int i; | ||
1537 | |||
1538 | while (!list_empty(lh)) { | ||
1539 | b = list_entry(lh->next, struct s5p_mfc_buf, list); | ||
1540 | for (i = 0; i < b->b->num_planes; i++) | ||
1541 | vb2_set_plane_payload(b->b, i, 0); | ||
1542 | vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR); | ||
1543 | list_del(&b->list); | ||
1544 | } | ||
1545 | } | ||
1546 | |||
1547 | void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev) | ||
1548 | { | ||
1549 | mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT); | ||
1550 | mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD); | ||
1551 | mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID); | ||
1552 | } | ||
1553 | |||
1554 | int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev) | ||
1555 | { | ||
1556 | return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT; | ||
1557 | } | ||
1558 | |||
1559 | int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev) | ||
1560 | { | ||
1561 | return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT; | ||
1562 | } | ||
1563 | |||
1564 | int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev) | ||
1565 | { | ||
1566 | return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS); | ||
1567 | } | ||
1568 | |||
1569 | int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev) | ||
1570 | { | ||
1571 | return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS); | ||
1572 | } | ||
1573 | |||
1574 | int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev) | ||
1575 | { | ||
1576 | return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) & | ||
1577 | S5P_FIMV_DECODE_FRAME_MASK; | ||
1578 | } | ||
1579 | |||
1580 | int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx) | ||
1581 | { | ||
1582 | return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >> | ||
1583 | S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) & | ||
1584 | S5P_FIMV_DECODE_FRAME_MASK; | ||
1585 | } | ||
1586 | |||
1587 | int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev) | ||
1588 | { | ||
1589 | return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES); | ||
1590 | } | ||
1591 | |||
1592 | int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev) | ||
1593 | { | ||
1594 | int reason; | ||
1595 | reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) & | ||
1596 | S5P_FIMV_RISC2HOST_CMD_MASK; | ||
1597 | switch (reason) { | ||
1598 | case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET: | ||
1599 | reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET; | ||
1600 | break; | ||
1601 | case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET: | ||
1602 | reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET; | ||
1603 | break; | ||
1604 | case S5P_FIMV_R2H_CMD_SEQ_DONE_RET: | ||
1605 | reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET; | ||
1606 | break; | ||
1607 | case S5P_FIMV_R2H_CMD_FRAME_DONE_RET: | ||
1608 | reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET; | ||
1609 | break; | ||
1610 | case S5P_FIMV_R2H_CMD_SLICE_DONE_RET: | ||
1611 | reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET; | ||
1612 | break; | ||
1613 | case S5P_FIMV_R2H_CMD_SYS_INIT_RET: | ||
1614 | reason = S5P_MFC_R2H_CMD_SYS_INIT_RET; | ||
1615 | break; | ||
1616 | case S5P_FIMV_R2H_CMD_FW_STATUS_RET: | ||
1617 | reason = S5P_MFC_R2H_CMD_FW_STATUS_RET; | ||
1618 | break; | ||
1619 | case S5P_FIMV_R2H_CMD_SLEEP_RET: | ||
1620 | reason = S5P_MFC_R2H_CMD_SLEEP_RET; | ||
1621 | break; | ||
1622 | case S5P_FIMV_R2H_CMD_WAKEUP_RET: | ||
1623 | reason = S5P_MFC_R2H_CMD_WAKEUP_RET; | ||
1624 | break; | ||
1625 | case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: | ||
1626 | reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET; | ||
1627 | break; | ||
1628 | case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET: | ||
1629 | reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET; | ||
1630 | break; | ||
1631 | case S5P_FIMV_R2H_CMD_ERR_RET: | ||
1632 | reason = S5P_MFC_R2H_CMD_ERR_RET; | ||
1633 | break; | ||
1634 | default: | ||
1635 | reason = S5P_MFC_R2H_CMD_EMPTY; | ||
1636 | }; | ||
1637 | return reason; | ||
1638 | } | ||
1639 | |||
1640 | int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev) | ||
1641 | { | ||
1642 | return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2); | ||
1643 | } | ||
1644 | |||
1645 | int s5p_mfc_err_dec_v5(unsigned int err) | ||
1646 | { | ||
1647 | return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT; | ||
1648 | } | ||
1649 | |||
1650 | int s5p_mfc_err_dspl_v5(unsigned int err) | ||
1651 | { | ||
1652 | return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT; | ||
1653 | } | ||
1654 | |||
1655 | int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev) | ||
1656 | { | ||
1657 | return mfc_read(dev, S5P_FIMV_SI_HRESOL); | ||
1658 | } | ||
1659 | |||
1660 | int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev) | ||
1661 | { | ||
1662 | return mfc_read(dev, S5P_FIMV_SI_VRESOL); | ||
1663 | } | ||
1664 | |||
1665 | int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev) | ||
1666 | { | ||
1667 | return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER); | ||
1668 | } | ||
1669 | |||
1670 | int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev) | ||
1671 | { | ||
1672 | /* NOP */ | ||
1673 | return -1; | ||
1674 | } | ||
1675 | |||
1676 | int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev) | ||
1677 | { | ||
1678 | return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1); | ||
1679 | } | ||
1680 | |||
1681 | int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev) | ||
1682 | { | ||
1683 | return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE); | ||
1684 | } | ||
1685 | |||
1686 | int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev) | ||
1687 | { | ||
1688 | return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE); | ||
1689 | } | ||
1690 | |||
1691 | int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev) | ||
1692 | { | ||
1693 | return -1; | ||
1694 | } | ||
1695 | |||
1696 | int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev) | ||
1697 | { | ||
1698 | return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT); | ||
1699 | } | ||
1700 | |||
1701 | int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx) | ||
1702 | { | ||
1703 | return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL); | ||
1704 | } | ||
1705 | |||
1706 | int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev) | ||
1707 | { | ||
1708 | return -1; | ||
1709 | } | ||
1710 | |||
1711 | int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev) | ||
1712 | { | ||
1713 | return -1; | ||
1714 | } | ||
1715 | |||
1716 | unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx) | ||
1717 | { | ||
1718 | return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP); | ||
1719 | } | ||
1720 | |||
1721 | unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx) | ||
1722 | { | ||
1723 | return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT); | ||
1724 | } | ||
1725 | |||
1726 | unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx) | ||
1727 | { | ||
1728 | return s5p_mfc_read_info_v5(ctx, CROP_INFO_H); | ||
1729 | } | ||
1730 | |||
1731 | unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx) | ||
1732 | { | ||
1733 | return s5p_mfc_read_info_v5(ctx, CROP_INFO_V); | ||
1734 | } | ||
1735 | |||
1736 | /* Initialize opr function pointers for MFC v5 */ | ||
1737 | static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = { | ||
1738 | .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5, | ||
1739 | .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5, | ||
1740 | .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5, | ||
1741 | .release_codec_buffers = s5p_mfc_release_codec_buffers_v5, | ||
1742 | .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5, | ||
1743 | .release_instance_buffer = s5p_mfc_release_instance_buffer_v5, | ||
1744 | .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5, | ||
1745 | .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5, | ||
1746 | .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5, | ||
1747 | .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5, | ||
1748 | .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v5, | ||
1749 | .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v5, | ||
1750 | .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5, | ||
1751 | .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5, | ||
1752 | .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5, | ||
1753 | .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v5, | ||
1754 | .init_decode = s5p_mfc_init_decode_v5, | ||
1755 | .init_encode = s5p_mfc_init_encode_v5, | ||
1756 | .encode_one_frame = s5p_mfc_encode_one_frame_v5, | ||
1757 | .try_run = s5p_mfc_try_run_v5, | ||
1758 | .cleanup_queue = s5p_mfc_cleanup_queue_v5, | ||
1759 | .clear_int_flags = s5p_mfc_clear_int_flags_v5, | ||
1760 | .write_info = s5p_mfc_write_info_v5, | ||
1761 | .read_info = s5p_mfc_read_info_v5, | ||
1762 | .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5, | ||
1763 | .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5, | ||
1764 | .get_dspl_status = s5p_mfc_get_dspl_status_v5, | ||
1765 | .get_dec_status = s5p_mfc_get_dec_status_v5, | ||
1766 | .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5, | ||
1767 | .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5, | ||
1768 | .get_consumed_stream = s5p_mfc_get_consumed_stream_v5, | ||
1769 | .get_int_reason = s5p_mfc_get_int_reason_v5, | ||
1770 | .get_int_err = s5p_mfc_get_int_err_v5, | ||
1771 | .err_dec = s5p_mfc_err_dec_v5, | ||
1772 | .err_dspl = s5p_mfc_err_dspl_v5, | ||
1773 | .get_img_width = s5p_mfc_get_img_width_v5, | ||
1774 | .get_img_height = s5p_mfc_get_img_height_v5, | ||
1775 | .get_dpb_count = s5p_mfc_get_dpb_count_v5, | ||
1776 | .get_mv_count = s5p_mfc_get_mv_count_v5, | ||
1777 | .get_inst_no = s5p_mfc_get_inst_no_v5, | ||
1778 | .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5, | ||
1779 | .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5, | ||
1780 | .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5, | ||
1781 | .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v5, | ||
1782 | .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v5, | ||
1783 | .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v5, | ||
1784 | .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v5, | ||
1785 | .get_pic_type_top = s5p_mfc_get_pic_type_top_v5, | ||
1786 | .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5, | ||
1787 | .get_crop_info_h = s5p_mfc_get_crop_info_h_v5, | ||
1788 | .get_crop_info_v = s5p_mfc_get_crop_info_v_v5, | ||
1789 | }; | ||
1790 | |||
1791 | struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void) | ||
1792 | { | ||
1793 | return &s5p_mfc_ops_v5; | ||
1794 | } | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h index 416ebd7ba35a..ffee39a127d5 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h | |||
@@ -1,17 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h | 2 | * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.h |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | 4 | * Header file for Samsung MFC (Multi Function Codec - FIMV) driver |
5 | * http://www.samsung.com/ | 5 | * Contains declarations of hw related functions. |
6 | * | ||
7 | * Kamil Debski, Copyright (C) 2011 Samsung Electronics | ||
8 | * http://www.samsung.com/ | ||
6 | * | 9 | * |
7 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License version 2 as |
9 | * the Free Software Foundation; either version 2 of the License, or | 12 | * published by the Free Software Foundation. |
10 | * (at your option) any later version. | ||
11 | */ | 13 | */ |
12 | 14 | ||
13 | #ifndef S5P_MFC_SHM_H_ | 15 | #ifndef S5P_MFC_OPR_V5_H_ |
14 | #define S5P_MFC_SHM_H_ | 16 | #define S5P_MFC_OPR_V5_H_ |
17 | |||
18 | #include "s5p_mfc_common.h" | ||
19 | #include "s5p_mfc_opr.h" | ||
15 | 20 | ||
16 | enum MFC_SHM_OFS { | 21 | enum MFC_SHM_OFS { |
17 | EXTENEDED_DECODE_STATUS = 0x00, /* D */ | 22 | EXTENEDED_DECODE_STATUS = 0x00, /* D */ |
@@ -71,20 +76,10 @@ enum MFC_SHM_OFS { | |||
71 | DBG_HISTORY_INPUT1 = 0xD4, /* C */ | 76 | DBG_HISTORY_INPUT1 = 0xD4, /* C */ |
72 | DBG_HISTORY_OUTPUT = 0xD8, /* C */ | 77 | DBG_HISTORY_OUTPUT = 0xD8, /* C */ |
73 | HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */ | 78 | HIERARCHICAL_P_QP = 0xE0, /* E, H.264 */ |
79 | FRAME_PACK_SEI_ENABLE = 0x168, /* C */ | ||
80 | FRAME_PACK_SEI_AVAIL = 0x16c, /* D */ | ||
81 | FRAME_PACK_SEI_INFO = 0x17c, /* E */ | ||
74 | }; | 82 | }; |
75 | 83 | ||
76 | int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx); | 84 | struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void); |
77 | 85 | #endif /* S5P_MFC_OPR_H_ */ | |
78 | #define s5p_mfc_write_shm(ctx, x, ofs) \ | ||
79 | do { \ | ||
80 | writel(x, (ctx->shm + ofs)); \ | ||
81 | wmb(); \ | ||
82 | } while (0) | ||
83 | |||
84 | static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs) | ||
85 | { | ||
86 | rmb(); | ||
87 | return readl(ctx->shm + ofs); | ||
88 | } | ||
89 | |||
90 | #endif /* S5P_MFC_SHM_H_ */ | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c new file mode 100644 index 000000000000..50b5bee3c44e --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |||
@@ -0,0 +1,1956 @@ | |||
1 | /* | ||
2 | * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | ||
3 | * | ||
4 | * Samsung MFC (Multi Function Codec - FIMV) driver | ||
5 | * This file contains hw related functions. | ||
6 | * | ||
7 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
8 | * http://www.samsung.com/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #undef DEBUG | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/jiffies.h> | ||
21 | #include <linux/firmware.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | |||
26 | #include <asm/cacheflush.h> | ||
27 | |||
28 | #include "s5p_mfc_common.h" | ||
29 | #include "s5p_mfc_cmd.h" | ||
30 | #include "s5p_mfc_intr.h" | ||
31 | #include "s5p_mfc_pm.h" | ||
32 | #include "s5p_mfc_debug.h" | ||
33 | #include "s5p_mfc_opr.h" | ||
34 | #include "s5p_mfc_opr_v6.h" | ||
35 | |||
36 | /* #define S5P_MFC_DEBUG_REGWRITE */ | ||
37 | #ifdef S5P_MFC_DEBUG_REGWRITE | ||
38 | #undef writel | ||
39 | #define writel(v, r) \ | ||
40 | do { \ | ||
41 | pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v); \ | ||
42 | __raw_writel(v, r); \ | ||
43 | } while (0) | ||
44 | #endif /* S5P_MFC_DEBUG_REGWRITE */ | ||
45 | |||
46 | #define READL(offset) readl(dev->regs_base + (offset)) | ||
47 | #define WRITEL(data, offset) writel((data), dev->regs_base + (offset)) | ||
48 | #define OFFSETA(x) (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET) | ||
49 | #define OFFSETB(x) (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET) | ||
50 | |||
51 | /* Allocate temporary buffers for decoding */ | ||
52 | int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) | ||
53 | { | ||
54 | /* NOP */ | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | /* Release temproary buffers for decoding */ | ||
60 | void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx) | ||
61 | { | ||
62 | /* NOP */ | ||
63 | } | ||
64 | |||
65 | int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) | ||
66 | { | ||
67 | /* NOP */ | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | /* Allocate codec buffers */ | ||
72 | int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | ||
73 | { | ||
74 | struct s5p_mfc_dev *dev = ctx->dev; | ||
75 | unsigned int mb_width, mb_height; | ||
76 | |||
77 | mb_width = MB_WIDTH(ctx->img_width); | ||
78 | mb_height = MB_HEIGHT(ctx->img_height); | ||
79 | |||
80 | if (ctx->type == MFCINST_DECODER) { | ||
81 | mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n", | ||
82 | ctx->luma_size, ctx->chroma_size, ctx->mv_size); | ||
83 | mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count); | ||
84 | } else if (ctx->type == MFCINST_ENCODER) { | ||
85 | ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | ||
86 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), | ||
87 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); | ||
88 | ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * | ||
89 | S5P_FIMV_LUMA_MB_TO_PIXEL_V6, | ||
90 | S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); | ||
91 | ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * | ||
92 | S5P_FIMV_CHROMA_MB_TO_PIXEL_V6, | ||
93 | S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6); | ||
94 | ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6( | ||
95 | ctx->img_width, ctx->img_height, | ||
96 | mb_width, mb_height), | ||
97 | S5P_FIMV_ME_BUFFER_ALIGN_V6); | ||
98 | |||
99 | mfc_debug(2, "recon luma size: %d chroma size: %d\n", | ||
100 | ctx->luma_dpb_size, ctx->chroma_dpb_size); | ||
101 | } else { | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | /* Codecs have different memory requirements */ | ||
106 | switch (ctx->codec_mode) { | ||
107 | case S5P_MFC_CODEC_H264_DEC: | ||
108 | case S5P_MFC_CODEC_H264_MVC_DEC: | ||
109 | ctx->scratch_buf_size = | ||
110 | S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6( | ||
111 | mb_width, | ||
112 | mb_height); | ||
113 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
114 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
115 | ctx->bank1_size = | ||
116 | ctx->scratch_buf_size + | ||
117 | (ctx->mv_count * ctx->mv_size); | ||
118 | break; | ||
119 | case S5P_MFC_CODEC_MPEG4_DEC: | ||
120 | ctx->scratch_buf_size = | ||
121 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( | ||
122 | mb_width, | ||
123 | mb_height); | ||
124 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
125 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
126 | ctx->bank1_size = ctx->scratch_buf_size; | ||
127 | break; | ||
128 | case S5P_MFC_CODEC_VC1RCV_DEC: | ||
129 | case S5P_MFC_CODEC_VC1_DEC: | ||
130 | ctx->scratch_buf_size = | ||
131 | S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6( | ||
132 | mb_width, | ||
133 | mb_height); | ||
134 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
135 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
136 | ctx->bank1_size = ctx->scratch_buf_size; | ||
137 | break; | ||
138 | case S5P_MFC_CODEC_MPEG2_DEC: | ||
139 | ctx->bank1_size = 0; | ||
140 | ctx->bank2_size = 0; | ||
141 | break; | ||
142 | case S5P_MFC_CODEC_H263_DEC: | ||
143 | ctx->scratch_buf_size = | ||
144 | S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6( | ||
145 | mb_width, | ||
146 | mb_height); | ||
147 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
148 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
149 | ctx->bank1_size = ctx->scratch_buf_size; | ||
150 | break; | ||
151 | case S5P_MFC_CODEC_VP8_DEC: | ||
152 | ctx->scratch_buf_size = | ||
153 | S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6( | ||
154 | mb_width, | ||
155 | mb_height); | ||
156 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
157 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
158 | ctx->bank1_size = ctx->scratch_buf_size; | ||
159 | break; | ||
160 | case S5P_MFC_CODEC_H264_ENC: | ||
161 | ctx->scratch_buf_size = | ||
162 | S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6( | ||
163 | mb_width, | ||
164 | mb_height); | ||
165 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
166 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
167 | ctx->bank1_size = | ||
168 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | ||
169 | (ctx->dpb_count * (ctx->luma_dpb_size + | ||
170 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | ||
171 | ctx->bank2_size = 0; | ||
172 | break; | ||
173 | case S5P_MFC_CODEC_MPEG4_ENC: | ||
174 | case S5P_MFC_CODEC_H263_ENC: | ||
175 | ctx->scratch_buf_size = | ||
176 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6( | ||
177 | mb_width, | ||
178 | mb_height); | ||
179 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
180 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
181 | ctx->bank1_size = | ||
182 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | ||
183 | (ctx->dpb_count * (ctx->luma_dpb_size + | ||
184 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | ||
185 | ctx->bank2_size = 0; | ||
186 | break; | ||
187 | default: | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | /* Allocate only if memory from bank 1 is necessary */ | ||
192 | if (ctx->bank1_size > 0) { | ||
193 | ctx->bank1_buf = vb2_dma_contig_memops.alloc( | ||
194 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size); | ||
195 | if (IS_ERR(ctx->bank1_buf)) { | ||
196 | ctx->bank1_buf = 0; | ||
197 | pr_err("Buf alloc for decoding failed (port A)\n"); | ||
198 | return -ENOMEM; | ||
199 | } | ||
200 | ctx->bank1_phys = s5p_mfc_mem_cookie( | ||
201 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf); | ||
202 | BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
203 | } | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | /* Release buffers allocated for codec */ | ||
209 | void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | ||
210 | { | ||
211 | if (ctx->bank1_buf) { | ||
212 | vb2_dma_contig_memops.put(ctx->bank1_buf); | ||
213 | ctx->bank1_buf = 0; | ||
214 | ctx->bank1_phys = 0; | ||
215 | ctx->bank1_size = 0; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* Allocate memory for instance data buffer */ | ||
220 | int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | ||
221 | { | ||
222 | struct s5p_mfc_dev *dev = ctx->dev; | ||
223 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | ||
224 | |||
225 | mfc_debug_enter(); | ||
226 | |||
227 | switch (ctx->codec_mode) { | ||
228 | case S5P_MFC_CODEC_H264_DEC: | ||
229 | case S5P_MFC_CODEC_H264_MVC_DEC: | ||
230 | ctx->ctx.size = buf_size->h264_dec_ctx; | ||
231 | break; | ||
232 | case S5P_MFC_CODEC_MPEG4_DEC: | ||
233 | case S5P_MFC_CODEC_H263_DEC: | ||
234 | case S5P_MFC_CODEC_VC1RCV_DEC: | ||
235 | case S5P_MFC_CODEC_VC1_DEC: | ||
236 | case S5P_MFC_CODEC_MPEG2_DEC: | ||
237 | case S5P_MFC_CODEC_VP8_DEC: | ||
238 | ctx->ctx.size = buf_size->other_dec_ctx; | ||
239 | break; | ||
240 | case S5P_MFC_CODEC_H264_ENC: | ||
241 | ctx->ctx.size = buf_size->h264_enc_ctx; | ||
242 | break; | ||
243 | case S5P_MFC_CODEC_MPEG4_ENC: | ||
244 | case S5P_MFC_CODEC_H263_ENC: | ||
245 | ctx->ctx.size = buf_size->other_enc_ctx; | ||
246 | break; | ||
247 | default: | ||
248 | ctx->ctx.size = 0; | ||
249 | mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode); | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | ctx->ctx.alloc = vb2_dma_contig_memops.alloc( | ||
254 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.size); | ||
255 | if (IS_ERR(ctx->ctx.alloc)) { | ||
256 | mfc_err("Allocating context buffer failed.\n"); | ||
257 | return PTR_ERR(ctx->ctx.alloc); | ||
258 | } | ||
259 | |||
260 | ctx->ctx.dma = s5p_mfc_mem_cookie( | ||
261 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc); | ||
262 | |||
263 | ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc); | ||
264 | if (!ctx->ctx.virt) { | ||
265 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
266 | ctx->ctx.alloc = NULL; | ||
267 | ctx->ctx.dma = 0; | ||
268 | ctx->ctx.virt = NULL; | ||
269 | |||
270 | mfc_err("Remapping context buffer failed.\n"); | ||
271 | return -ENOMEM; | ||
272 | } | ||
273 | |||
274 | memset(ctx->ctx.virt, 0, ctx->ctx.size); | ||
275 | wmb(); | ||
276 | |||
277 | mfc_debug_leave(); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* Release instance buffer */ | ||
283 | void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | ||
284 | { | ||
285 | mfc_debug_enter(); | ||
286 | |||
287 | if (ctx->ctx.alloc) { | ||
288 | vb2_dma_contig_memops.put(ctx->ctx.alloc); | ||
289 | ctx->ctx.alloc = NULL; | ||
290 | ctx->ctx.dma = 0; | ||
291 | ctx->ctx.virt = NULL; | ||
292 | } | ||
293 | |||
294 | mfc_debug_leave(); | ||
295 | } | ||
296 | |||
297 | /* Allocate context buffers for SYS_INIT */ | ||
298 | int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) | ||
299 | { | ||
300 | struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; | ||
301 | |||
302 | mfc_debug_enter(); | ||
303 | |||
304 | dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc( | ||
305 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx); | ||
306 | if (IS_ERR(dev->ctx_buf.alloc)) { | ||
307 | mfc_err("Allocating DESC buffer failed.\n"); | ||
308 | return PTR_ERR(dev->ctx_buf.alloc); | ||
309 | } | ||
310 | |||
311 | dev->ctx_buf.dma = s5p_mfc_mem_cookie( | ||
312 | dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], | ||
313 | dev->ctx_buf.alloc); | ||
314 | |||
315 | dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc); | ||
316 | if (!dev->ctx_buf.virt) { | ||
317 | vb2_dma_contig_memops.put(dev->ctx_buf.alloc); | ||
318 | dev->ctx_buf.alloc = NULL; | ||
319 | dev->ctx_buf.dma = 0; | ||
320 | |||
321 | mfc_err("Remapping DESC buffer failed.\n"); | ||
322 | return -ENOMEM; | ||
323 | } | ||
324 | |||
325 | memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx); | ||
326 | wmb(); | ||
327 | |||
328 | mfc_debug_leave(); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* Release context buffers for SYS_INIT */ | ||
334 | void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) | ||
335 | { | ||
336 | if (dev->ctx_buf.alloc) { | ||
337 | vb2_dma_contig_memops.put(dev->ctx_buf.alloc); | ||
338 | dev->ctx_buf.alloc = NULL; | ||
339 | dev->ctx_buf.dma = 0; | ||
340 | dev->ctx_buf.virt = NULL; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static int calc_plane(int width, int height) | ||
345 | { | ||
346 | int mbX, mbY; | ||
347 | |||
348 | mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6); | ||
349 | mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6); | ||
350 | |||
351 | if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6) | ||
352 | mbY = (mbY + 1) / 2 * 2; | ||
353 | |||
354 | return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) * | ||
355 | (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6); | ||
356 | } | ||
357 | |||
358 | void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) | ||
359 | { | ||
360 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6); | ||
361 | ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6); | ||
362 | mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n" | ||
363 | "buffer dimensions: %dx%d\n", ctx->img_width, | ||
364 | ctx->img_height, ctx->buf_width, ctx->buf_height); | ||
365 | |||
366 | ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height); | ||
367 | ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1)); | ||
368 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | ||
369 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { | ||
370 | ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width, | ||
371 | ctx->img_height); | ||
372 | ctx->mv_size = ALIGN(ctx->mv_size, 16); | ||
373 | } else { | ||
374 | ctx->mv_size = 0; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) | ||
379 | { | ||
380 | unsigned int mb_width, mb_height; | ||
381 | |||
382 | mb_width = MB_WIDTH(ctx->img_width); | ||
383 | mb_height = MB_HEIGHT(ctx->img_height); | ||
384 | |||
385 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); | ||
386 | ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); | ||
387 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); | ||
388 | } | ||
389 | |||
390 | /* Set registers for decoding stream buffer */ | ||
391 | int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr, | ||
392 | unsigned int start_num_byte, unsigned int strm_size) | ||
393 | { | ||
394 | struct s5p_mfc_dev *dev = ctx->dev; | ||
395 | struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; | ||
396 | |||
397 | mfc_debug_enter(); | ||
398 | mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n" | ||
399 | "buf_size: 0x%08x (%d)\n", | ||
400 | ctx->inst_no, buf_addr, strm_size, strm_size); | ||
401 | WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6); | ||
402 | WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6); | ||
403 | WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6); | ||
404 | WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6); | ||
405 | |||
406 | mfc_debug_leave(); | ||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | /* Set decoding frame buffer */ | ||
411 | int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) | ||
412 | { | ||
413 | unsigned int frame_size, i; | ||
414 | unsigned int frame_size_ch, frame_size_mv; | ||
415 | struct s5p_mfc_dev *dev = ctx->dev; | ||
416 | size_t buf_addr1; | ||
417 | int buf_size1; | ||
418 | int align_gap; | ||
419 | |||
420 | buf_addr1 = ctx->bank1_phys; | ||
421 | buf_size1 = ctx->bank1_size; | ||
422 | |||
423 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | ||
424 | mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count); | ||
425 | mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay); | ||
426 | |||
427 | WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB_V6); | ||
428 | WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6); | ||
429 | WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6); | ||
430 | |||
431 | WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6); | ||
432 | WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6); | ||
433 | buf_addr1 += ctx->scratch_buf_size; | ||
434 | buf_size1 -= ctx->scratch_buf_size; | ||
435 | |||
436 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC || | ||
437 | ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){ | ||
438 | WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6); | ||
439 | WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6); | ||
440 | } | ||
441 | |||
442 | frame_size = ctx->luma_size; | ||
443 | frame_size_ch = ctx->chroma_size; | ||
444 | frame_size_mv = ctx->mv_size; | ||
445 | mfc_debug(2, "Frame size: %d ch: %d mv: %d\n", | ||
446 | frame_size, frame_size_ch, frame_size_mv); | ||
447 | |||
448 | for (i = 0; i < ctx->total_dpb_count; i++) { | ||
449 | /* Bank2 */ | ||
450 | mfc_debug(2, "Luma %d: %x\n", i, | ||
451 | ctx->dst_bufs[i].cookie.raw.luma); | ||
452 | WRITEL(ctx->dst_bufs[i].cookie.raw.luma, | ||
453 | S5P_FIMV_D_LUMA_DPB_V6 + i * 4); | ||
454 | mfc_debug(2, "\tChroma %d: %x\n", i, | ||
455 | ctx->dst_bufs[i].cookie.raw.chroma); | ||
456 | WRITEL(ctx->dst_bufs[i].cookie.raw.chroma, | ||
457 | S5P_FIMV_D_CHROMA_DPB_V6 + i * 4); | ||
458 | } | ||
459 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || | ||
460 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { | ||
461 | for (i = 0; i < ctx->mv_count; i++) { | ||
462 | /* To test alignment */ | ||
463 | align_gap = buf_addr1; | ||
464 | buf_addr1 = ALIGN(buf_addr1, 16); | ||
465 | align_gap = buf_addr1 - align_gap; | ||
466 | buf_size1 -= align_gap; | ||
467 | |||
468 | mfc_debug(2, "\tBuf1: %x, size: %d\n", | ||
469 | buf_addr1, buf_size1); | ||
470 | WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4); | ||
471 | buf_addr1 += frame_size_mv; | ||
472 | buf_size1 -= frame_size_mv; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n", | ||
477 | buf_addr1, buf_size1, ctx->total_dpb_count); | ||
478 | if (buf_size1 < 0) { | ||
479 | mfc_debug(2, "Not enough memory has been allocated.\n"); | ||
480 | return -ENOMEM; | ||
481 | } | ||
482 | |||
483 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
484 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
485 | S5P_FIMV_CH_INIT_BUFS_V6, NULL); | ||
486 | |||
487 | mfc_debug(2, "After setting buffers.\n"); | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | /* Set registers for encoding stream buffer */ | ||
492 | int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, | ||
493 | unsigned long addr, unsigned int size) | ||
494 | { | ||
495 | struct s5p_mfc_dev *dev = ctx->dev; | ||
496 | |||
497 | WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */ | ||
498 | WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); | ||
499 | |||
500 | mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d", | ||
501 | addr, size); | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | ||
507 | unsigned long y_addr, unsigned long c_addr) | ||
508 | { | ||
509 | struct s5p_mfc_dev *dev = ctx->dev; | ||
510 | |||
511 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */ | ||
512 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | ||
513 | |||
514 | mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr); | ||
515 | mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr); | ||
516 | } | ||
517 | |||
518 | void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | ||
519 | unsigned long *y_addr, unsigned long *c_addr) | ||
520 | { | ||
521 | struct s5p_mfc_dev *dev = ctx->dev; | ||
522 | unsigned long enc_recon_y_addr, enc_recon_c_addr; | ||
523 | |||
524 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | ||
525 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | ||
526 | |||
527 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | ||
528 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | ||
529 | |||
530 | mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr); | ||
531 | mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr); | ||
532 | } | ||
533 | |||
534 | /* Set encoding ref & codec buffer */ | ||
535 | int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) | ||
536 | { | ||
537 | struct s5p_mfc_dev *dev = ctx->dev; | ||
538 | size_t buf_addr1, buf_size1; | ||
539 | int i; | ||
540 | |||
541 | mfc_debug_enter(); | ||
542 | |||
543 | buf_addr1 = ctx->bank1_phys; | ||
544 | buf_size1 = ctx->bank1_size; | ||
545 | |||
546 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | ||
547 | |||
548 | for (i = 0; i < ctx->dpb_count; i++) { | ||
549 | WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i)); | ||
550 | buf_addr1 += ctx->luma_dpb_size; | ||
551 | WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i)); | ||
552 | buf_addr1 += ctx->chroma_dpb_size; | ||
553 | WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i)); | ||
554 | buf_addr1 += ctx->me_buffer_size; | ||
555 | buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size + | ||
556 | ctx->me_buffer_size); | ||
557 | } | ||
558 | |||
559 | WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6); | ||
560 | WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6); | ||
561 | buf_addr1 += ctx->scratch_buf_size; | ||
562 | buf_size1 -= ctx->scratch_buf_size; | ||
563 | |||
564 | WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6); | ||
565 | buf_addr1 += ctx->tmv_buffer_size >> 1; | ||
566 | WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6); | ||
567 | buf_addr1 += ctx->tmv_buffer_size >> 1; | ||
568 | buf_size1 -= ctx->tmv_buffer_size; | ||
569 | |||
570 | mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n", | ||
571 | buf_addr1, buf_size1, ctx->dpb_count); | ||
572 | if (buf_size1 < 0) { | ||
573 | mfc_debug(2, "Not enough memory has been allocated.\n"); | ||
574 | return -ENOMEM; | ||
575 | } | ||
576 | |||
577 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
578 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
579 | S5P_FIMV_CH_INIT_BUFS_V6, NULL); | ||
580 | |||
581 | mfc_debug_leave(); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx) | ||
587 | { | ||
588 | struct s5p_mfc_dev *dev = ctx->dev; | ||
589 | |||
590 | /* multi-slice control */ | ||
591 | /* multi-slice MB number or bit size */ | ||
592 | WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6); | ||
593 | if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { | ||
594 | WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6); | ||
595 | } else if (ctx->slice_mode == | ||
596 | V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { | ||
597 | WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); | ||
598 | } else { | ||
599 | WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6); | ||
600 | WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); | ||
601 | } | ||
602 | |||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) | ||
607 | { | ||
608 | struct s5p_mfc_dev *dev = ctx->dev; | ||
609 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
610 | unsigned int reg = 0; | ||
611 | |||
612 | mfc_debug_enter(); | ||
613 | |||
614 | /* width */ | ||
615 | WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH_V6); /* 16 align */ | ||
616 | /* height */ | ||
617 | WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */ | ||
618 | |||
619 | /* cropped width */ | ||
620 | WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6); | ||
621 | /* cropped height */ | ||
622 | WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); | ||
623 | /* cropped offset */ | ||
624 | WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6); | ||
625 | |||
626 | /* pictype : IDR period */ | ||
627 | reg = 0; | ||
628 | reg |= p->gop_size & 0xFFFF; | ||
629 | WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | ||
630 | |||
631 | /* multi-slice control */ | ||
632 | /* multi-slice MB number or bit size */ | ||
633 | ctx->slice_mode = p->slice_mode; | ||
634 | reg = 0; | ||
635 | if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { | ||
636 | reg |= (0x1 << 3); | ||
637 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
638 | ctx->slice_size.mb = p->slice_mb; | ||
639 | } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { | ||
640 | reg |= (0x1 << 3); | ||
641 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
642 | ctx->slice_size.bits = p->slice_bit; | ||
643 | } else { | ||
644 | reg &= ~(0x1 << 3); | ||
645 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
646 | } | ||
647 | |||
648 | s5p_mfc_set_slice_mode(ctx); | ||
649 | |||
650 | /* cyclic intra refresh */ | ||
651 | WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6); | ||
652 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
653 | if (p->intra_refresh_mb == 0) | ||
654 | reg &= ~(0x1 << 4); | ||
655 | else | ||
656 | reg |= (0x1 << 4); | ||
657 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
658 | |||
659 | /* 'NON_REFERENCE_STORE_ENABLE' for debugging */ | ||
660 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
661 | reg &= ~(0x1 << 9); | ||
662 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
663 | |||
664 | /* memory structure cur. frame */ | ||
665 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) { | ||
666 | /* 0: Linear, 1: 2D tiled*/ | ||
667 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
668 | reg &= ~(0x1 << 7); | ||
669 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
670 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | ||
671 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | ||
672 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) { | ||
673 | /* 0: Linear, 1: 2D tiled*/ | ||
674 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
675 | reg &= ~(0x1 << 7); | ||
676 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
677 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | ||
678 | WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6); | ||
679 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { | ||
680 | /* 0: Linear, 1: 2D tiled*/ | ||
681 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
682 | reg |= (0x1 << 7); | ||
683 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
684 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | ||
685 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | ||
686 | } | ||
687 | |||
688 | /* memory structure recon. frame */ | ||
689 | /* 0: Linear, 1: 2D tiled */ | ||
690 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
691 | reg |= (0x1 << 8); | ||
692 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
693 | |||
694 | /* padding control & value */ | ||
695 | WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6); | ||
696 | if (p->pad) { | ||
697 | reg = 0; | ||
698 | /** enable */ | ||
699 | reg |= (1 << 31); | ||
700 | /** cr value */ | ||
701 | reg |= ((p->pad_cr & 0xFF) << 16); | ||
702 | /** cb value */ | ||
703 | reg |= ((p->pad_cb & 0xFF) << 8); | ||
704 | /** y value */ | ||
705 | reg |= p->pad_luma & 0xFF; | ||
706 | WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6); | ||
707 | } | ||
708 | |||
709 | /* rate control config. */ | ||
710 | reg = 0; | ||
711 | /* frame-level rate control */ | ||
712 | reg |= ((p->rc_frame & 0x1) << 9); | ||
713 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
714 | |||
715 | /* bit rate */ | ||
716 | if (p->rc_frame) | ||
717 | WRITEL(p->rc_bitrate, | ||
718 | S5P_FIMV_E_RC_BIT_RATE_V6); | ||
719 | else | ||
720 | WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6); | ||
721 | |||
722 | /* reaction coefficient */ | ||
723 | if (p->rc_frame) { | ||
724 | if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */ | ||
725 | WRITEL(1, S5P_FIMV_E_RC_RPARAM_V6); | ||
726 | else /* loose CBR */ | ||
727 | WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6); | ||
728 | } | ||
729 | |||
730 | /* seq header ctrl */ | ||
731 | reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | ||
732 | reg &= ~(0x1 << 2); | ||
733 | reg |= ((p->seq_hdr_mode & 0x1) << 2); | ||
734 | |||
735 | /* frame skip mode */ | ||
736 | reg &= ~(0x3); | ||
737 | reg |= (p->frame_skip_mode & 0x3); | ||
738 | WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | ||
739 | |||
740 | /* 'DROP_CONTROL_ENABLE', disable */ | ||
741 | reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | ||
742 | reg &= ~(0x1 << 10); | ||
743 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
744 | |||
745 | /* setting for MV range [16, 256] */ | ||
746 | reg = 0; | ||
747 | reg &= ~(0x3FFF); | ||
748 | reg = 256; | ||
749 | WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6); | ||
750 | |||
751 | reg = 0; | ||
752 | reg &= ~(0x3FFF); | ||
753 | reg = 256; | ||
754 | WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6); | ||
755 | |||
756 | WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6); | ||
757 | WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6); | ||
758 | WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6); | ||
759 | WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6); | ||
760 | WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6); | ||
761 | |||
762 | WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6); | ||
763 | WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6); | ||
764 | WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6); | ||
765 | |||
766 | WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6); | ||
767 | WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6); | ||
768 | |||
769 | mfc_debug_leave(); | ||
770 | |||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) | ||
775 | { | ||
776 | struct s5p_mfc_dev *dev = ctx->dev; | ||
777 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
778 | struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; | ||
779 | unsigned int reg = 0; | ||
780 | int i; | ||
781 | |||
782 | mfc_debug_enter(); | ||
783 | |||
784 | s5p_mfc_set_enc_params(ctx); | ||
785 | |||
786 | /* pictype : number of B */ | ||
787 | reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | ||
788 | reg &= ~(0x3 << 16); | ||
789 | reg |= ((p->num_b_frame & 0x3) << 16); | ||
790 | WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | ||
791 | |||
792 | /* profile & level */ | ||
793 | reg = 0; | ||
794 | /** level */ | ||
795 | reg |= ((p_h264->level & 0xFF) << 8); | ||
796 | /** profile - 0 ~ 3 */ | ||
797 | reg |= p_h264->profile & 0x3F; | ||
798 | WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | ||
799 | |||
800 | /* rate control config. */ | ||
801 | reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | ||
802 | /** macroblock level rate control */ | ||
803 | reg &= ~(0x1 << 8); | ||
804 | reg |= ((p->rc_mb & 0x1) << 8); | ||
805 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
806 | /** frame QP */ | ||
807 | reg &= ~(0x3F); | ||
808 | reg |= p_h264->rc_frame_qp & 0x3F; | ||
809 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
810 | |||
811 | /* max & min value of QP */ | ||
812 | reg = 0; | ||
813 | /** max QP */ | ||
814 | reg |= ((p_h264->rc_max_qp & 0x3F) << 8); | ||
815 | /** min QP */ | ||
816 | reg |= p_h264->rc_min_qp & 0x3F; | ||
817 | WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | ||
818 | |||
819 | /* other QPs */ | ||
820 | WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | ||
821 | if (!p->rc_frame && !p->rc_mb) { | ||
822 | reg = 0; | ||
823 | reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16); | ||
824 | reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8); | ||
825 | reg |= p_h264->rc_frame_qp & 0x3F; | ||
826 | WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | ||
827 | } | ||
828 | |||
829 | /* frame rate */ | ||
830 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | ||
831 | reg = 0; | ||
832 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | ||
833 | reg |= p->rc_framerate_denom & 0xFFFF; | ||
834 | WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | ||
835 | } | ||
836 | |||
837 | /* vbv buffer size */ | ||
838 | if (p->frame_skip_mode == | ||
839 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
840 | WRITEL(p_h264->cpb_size & 0xFFFF, | ||
841 | S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | ||
842 | |||
843 | if (p->rc_frame) | ||
844 | WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | ||
845 | } | ||
846 | |||
847 | /* interlace */ | ||
848 | reg = 0; | ||
849 | reg |= ((p_h264->interlace & 0x1) << 3); | ||
850 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
851 | |||
852 | /* height */ | ||
853 | if (p_h264->interlace) { | ||
854 | WRITEL(ctx->img_height >> 1, | ||
855 | S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */ | ||
856 | /* cropped height */ | ||
857 | WRITEL(ctx->img_height >> 1, | ||
858 | S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); | ||
859 | } | ||
860 | |||
861 | /* loop filter ctrl */ | ||
862 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
863 | reg &= ~(0x3 << 1); | ||
864 | reg |= ((p_h264->loop_filter_mode & 0x3) << 1); | ||
865 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
866 | |||
867 | /* loopfilter alpha offset */ | ||
868 | if (p_h264->loop_filter_alpha < 0) { | ||
869 | reg = 0x10; | ||
870 | reg |= (0xFF - p_h264->loop_filter_alpha) + 1; | ||
871 | } else { | ||
872 | reg = 0x00; | ||
873 | reg |= (p_h264->loop_filter_alpha & 0xF); | ||
874 | } | ||
875 | WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6); | ||
876 | |||
877 | /* loopfilter beta offset */ | ||
878 | if (p_h264->loop_filter_beta < 0) { | ||
879 | reg = 0x10; | ||
880 | reg |= (0xFF - p_h264->loop_filter_beta) + 1; | ||
881 | } else { | ||
882 | reg = 0x00; | ||
883 | reg |= (p_h264->loop_filter_beta & 0xF); | ||
884 | } | ||
885 | WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6); | ||
886 | |||
887 | /* entropy coding mode */ | ||
888 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
889 | reg &= ~(0x1); | ||
890 | reg |= p_h264->entropy_mode & 0x1; | ||
891 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
892 | |||
893 | /* number of ref. picture */ | ||
894 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
895 | reg &= ~(0x1 << 7); | ||
896 | reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7); | ||
897 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
898 | |||
899 | /* 8x8 transform enable */ | ||
900 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
901 | reg &= ~(0x3 << 12); | ||
902 | reg |= ((p_h264->_8x8_transform & 0x3) << 12); | ||
903 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
904 | |||
905 | /* macroblock adaptive scaling features */ | ||
906 | WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6); | ||
907 | if (p->rc_mb) { | ||
908 | reg = 0; | ||
909 | /** dark region */ | ||
910 | reg |= ((p_h264->rc_mb_dark & 0x1) << 3); | ||
911 | /** smooth region */ | ||
912 | reg |= ((p_h264->rc_mb_smooth & 0x1) << 2); | ||
913 | /** static region */ | ||
914 | reg |= ((p_h264->rc_mb_static & 0x1) << 1); | ||
915 | /** high activity region */ | ||
916 | reg |= p_h264->rc_mb_activity & 0x1; | ||
917 | WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG_V6); | ||
918 | } | ||
919 | |||
920 | /* aspect ratio VUI */ | ||
921 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
922 | reg &= ~(0x1 << 5); | ||
923 | reg |= ((p_h264->vui_sar & 0x1) << 5); | ||
924 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
925 | |||
926 | WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6); | ||
927 | WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6); | ||
928 | if (p_h264->vui_sar) { | ||
929 | /* aspect ration IDC */ | ||
930 | reg = 0; | ||
931 | reg |= p_h264->vui_sar_idc & 0xFF; | ||
932 | WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO_V6); | ||
933 | if (p_h264->vui_sar_idc == 0xFF) { | ||
934 | /* extended SAR */ | ||
935 | reg = 0; | ||
936 | reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16; | ||
937 | reg |= p_h264->vui_ext_sar_height & 0xFFFF; | ||
938 | WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR_V6); | ||
939 | } | ||
940 | } | ||
941 | |||
942 | /* intra picture period for H.264 open GOP */ | ||
943 | /* control */ | ||
944 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
945 | reg &= ~(0x1 << 4); | ||
946 | reg |= ((p_h264->open_gop & 0x1) << 4); | ||
947 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
948 | /* value */ | ||
949 | WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6); | ||
950 | if (p_h264->open_gop) { | ||
951 | reg = 0; | ||
952 | reg |= p_h264->open_gop_size & 0xFFFF; | ||
953 | WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD_V6); | ||
954 | } | ||
955 | |||
956 | /* 'WEIGHTED_BI_PREDICTION' for B is disable */ | ||
957 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
958 | reg &= ~(0x3 << 9); | ||
959 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
960 | |||
961 | /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */ | ||
962 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
963 | reg &= ~(0x1 << 14); | ||
964 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
965 | |||
966 | /* ASO */ | ||
967 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
968 | reg &= ~(0x1 << 6); | ||
969 | reg |= ((p_h264->aso & 0x1) << 6); | ||
970 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
971 | |||
972 | /* hier qp enable */ | ||
973 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
974 | reg &= ~(0x1 << 8); | ||
975 | reg |= ((p_h264->open_gop & 0x1) << 8); | ||
976 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
977 | reg = 0; | ||
978 | if (p_h264->hier_qp && p_h264->hier_qp_layer) { | ||
979 | reg |= (p_h264->hier_qp_type & 0x1) << 0x3; | ||
980 | reg |= p_h264->hier_qp_layer & 0x7; | ||
981 | WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6); | ||
982 | /* QP value for each layer */ | ||
983 | for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++) | ||
984 | WRITEL(p_h264->hier_qp_layer_qp[i], | ||
985 | S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 + | ||
986 | i * 4); | ||
987 | } | ||
988 | /* number of coding layer should be zero when hierarchical is disable */ | ||
989 | WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6); | ||
990 | |||
991 | /* frame packing SEI generation */ | ||
992 | reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | ||
993 | reg &= ~(0x1 << 25); | ||
994 | reg |= ((p_h264->sei_frame_packing & 0x1) << 25); | ||
995 | WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | ||
996 | if (p_h264->sei_frame_packing) { | ||
997 | reg = 0; | ||
998 | /** current frame0 flag */ | ||
999 | reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2); | ||
1000 | /** arrangement type */ | ||
1001 | reg |= p_h264->sei_fp_arrangement_type & 0x3; | ||
1002 | WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6); | ||
1003 | } | ||
1004 | |||
1005 | if (p_h264->fmo) { | ||
1006 | switch (p_h264->fmo_map_type) { | ||
1007 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES: | ||
1008 | if (p_h264->fmo_slice_grp > 4) | ||
1009 | p_h264->fmo_slice_grp = 4; | ||
1010 | for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++) | ||
1011 | WRITEL(p_h264->fmo_run_len[i] - 1, | ||
1012 | S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 + | ||
1013 | i * 4); | ||
1014 | break; | ||
1015 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES: | ||
1016 | if (p_h264->fmo_slice_grp > 4) | ||
1017 | p_h264->fmo_slice_grp = 4; | ||
1018 | break; | ||
1019 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN: | ||
1020 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN: | ||
1021 | if (p_h264->fmo_slice_grp > 2) | ||
1022 | p_h264->fmo_slice_grp = 2; | ||
1023 | WRITEL(p_h264->fmo_chg_dir & 0x1, | ||
1024 | S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6); | ||
1025 | /* the valid range is 0 ~ number of macroblocks -1 */ | ||
1026 | WRITEL(p_h264->fmo_chg_rate, | ||
1027 | S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6); | ||
1028 | break; | ||
1029 | default: | ||
1030 | mfc_err("Unsupported map type for FMO: %d\n", | ||
1031 | p_h264->fmo_map_type); | ||
1032 | p_h264->fmo_map_type = 0; | ||
1033 | p_h264->fmo_slice_grp = 1; | ||
1034 | break; | ||
1035 | } | ||
1036 | |||
1037 | WRITEL(p_h264->fmo_map_type, | ||
1038 | S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6); | ||
1039 | WRITEL(p_h264->fmo_slice_grp - 1, | ||
1040 | S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); | ||
1041 | } else { | ||
1042 | WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); | ||
1043 | } | ||
1044 | |||
1045 | mfc_debug_leave(); | ||
1046 | |||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1050 | static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) | ||
1051 | { | ||
1052 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1053 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
1054 | struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4; | ||
1055 | unsigned int reg = 0; | ||
1056 | |||
1057 | mfc_debug_enter(); | ||
1058 | |||
1059 | s5p_mfc_set_enc_params(ctx); | ||
1060 | |||
1061 | /* pictype : number of B */ | ||
1062 | reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | ||
1063 | reg &= ~(0x3 << 16); | ||
1064 | reg |= ((p->num_b_frame & 0x3) << 16); | ||
1065 | WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | ||
1066 | |||
1067 | /* profile & level */ | ||
1068 | reg = 0; | ||
1069 | /** level */ | ||
1070 | reg |= ((p_mpeg4->level & 0xFF) << 8); | ||
1071 | /** profile - 0 ~ 1 */ | ||
1072 | reg |= p_mpeg4->profile & 0x3F; | ||
1073 | WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | ||
1074 | |||
1075 | /* rate control config. */ | ||
1076 | reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | ||
1077 | /** macroblock level rate control */ | ||
1078 | reg &= ~(0x1 << 8); | ||
1079 | reg |= ((p->rc_mb & 0x1) << 8); | ||
1080 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
1081 | /** frame QP */ | ||
1082 | reg &= ~(0x3F); | ||
1083 | reg |= p_mpeg4->rc_frame_qp & 0x3F; | ||
1084 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
1085 | |||
1086 | /* max & min value of QP */ | ||
1087 | reg = 0; | ||
1088 | /** max QP */ | ||
1089 | reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8); | ||
1090 | /** min QP */ | ||
1091 | reg |= p_mpeg4->rc_min_qp & 0x3F; | ||
1092 | WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | ||
1093 | |||
1094 | /* other QPs */ | ||
1095 | WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | ||
1096 | if (!p->rc_frame && !p->rc_mb) { | ||
1097 | reg = 0; | ||
1098 | reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16); | ||
1099 | reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8); | ||
1100 | reg |= p_mpeg4->rc_frame_qp & 0x3F; | ||
1101 | WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | ||
1102 | } | ||
1103 | |||
1104 | /* frame rate */ | ||
1105 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | ||
1106 | reg = 0; | ||
1107 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | ||
1108 | reg |= p->rc_framerate_denom & 0xFFFF; | ||
1109 | WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | ||
1110 | } | ||
1111 | |||
1112 | /* vbv buffer size */ | ||
1113 | if (p->frame_skip_mode == | ||
1114 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
1115 | WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | ||
1116 | |||
1117 | if (p->rc_frame) | ||
1118 | WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | ||
1119 | } | ||
1120 | |||
1121 | /* Disable HEC */ | ||
1122 | WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6); | ||
1123 | WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6); | ||
1124 | |||
1125 | mfc_debug_leave(); | ||
1126 | |||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) | ||
1131 | { | ||
1132 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1133 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
1134 | struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4; | ||
1135 | unsigned int reg = 0; | ||
1136 | |||
1137 | mfc_debug_enter(); | ||
1138 | |||
1139 | s5p_mfc_set_enc_params(ctx); | ||
1140 | |||
1141 | /* profile & level */ | ||
1142 | reg = 0; | ||
1143 | /** profile */ | ||
1144 | reg |= (0x1 << 4); | ||
1145 | WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | ||
1146 | |||
1147 | /* rate control config. */ | ||
1148 | reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | ||
1149 | /** macroblock level rate control */ | ||
1150 | reg &= ~(0x1 << 8); | ||
1151 | reg |= ((p->rc_mb & 0x1) << 8); | ||
1152 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
1153 | /** frame QP */ | ||
1154 | reg &= ~(0x3F); | ||
1155 | reg |= p_h263->rc_frame_qp & 0x3F; | ||
1156 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
1157 | |||
1158 | /* max & min value of QP */ | ||
1159 | reg = 0; | ||
1160 | /** max QP */ | ||
1161 | reg |= ((p_h263->rc_max_qp & 0x3F) << 8); | ||
1162 | /** min QP */ | ||
1163 | reg |= p_h263->rc_min_qp & 0x3F; | ||
1164 | WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | ||
1165 | |||
1166 | /* other QPs */ | ||
1167 | WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | ||
1168 | if (!p->rc_frame && !p->rc_mb) { | ||
1169 | reg = 0; | ||
1170 | reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16); | ||
1171 | reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8); | ||
1172 | reg |= p_h263->rc_frame_qp & 0x3F; | ||
1173 | WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | ||
1174 | } | ||
1175 | |||
1176 | /* frame rate */ | ||
1177 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | ||
1178 | reg = 0; | ||
1179 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | ||
1180 | reg |= p->rc_framerate_denom & 0xFFFF; | ||
1181 | WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | ||
1182 | } | ||
1183 | |||
1184 | /* vbv buffer size */ | ||
1185 | if (p->frame_skip_mode == | ||
1186 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
1187 | WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | ||
1188 | |||
1189 | if (p->rc_frame) | ||
1190 | WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | ||
1191 | } | ||
1192 | |||
1193 | mfc_debug_leave(); | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | /* Initialize decoding */ | ||
1199 | int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | ||
1200 | { | ||
1201 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1202 | unsigned int reg = 0; | ||
1203 | int fmo_aso_ctrl = 0; | ||
1204 | |||
1205 | mfc_debug_enter(); | ||
1206 | mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, | ||
1207 | S5P_FIMV_CH_SEQ_HEADER_V6); | ||
1208 | mfc_debug(2, "BUFs: %08x %08x %08x\n", | ||
1209 | READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6), | ||
1210 | READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6), | ||
1211 | READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6)); | ||
1212 | |||
1213 | /* FMO_ASO_CTRL - 0: Enable, 1: Disable */ | ||
1214 | reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6); | ||
1215 | |||
1216 | /* When user sets desplay_delay to 0, | ||
1217 | * It works as "display_delay enable" and delay set to 0. | ||
1218 | * If user wants display_delay disable, It should be | ||
1219 | * set to negative value. */ | ||
1220 | if (ctx->display_delay >= 0) { | ||
1221 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); | ||
1222 | WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); | ||
1223 | } | ||
1224 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ | ||
1225 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { | ||
1226 | mfc_debug(2, "Set loop filter to: %d\n", | ||
1227 | ctx->loop_filter_mpeg4); | ||
1228 | reg |= (ctx->loop_filter_mpeg4 << | ||
1229 | S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6); | ||
1230 | } | ||
1231 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) | ||
1232 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); | ||
1233 | |||
1234 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | ||
1235 | |||
1236 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | ||
1237 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) | ||
1238 | WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6); | ||
1239 | else | ||
1240 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | ||
1241 | |||
1242 | /* sei parse */ | ||
1243 | WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); | ||
1244 | |||
1245 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
1246 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
1247 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); | ||
1248 | |||
1249 | mfc_debug_leave(); | ||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) | ||
1254 | { | ||
1255 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1256 | unsigned int dpb; | ||
1257 | if (flush) | ||
1258 | dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14); | ||
1259 | else | ||
1260 | dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14); | ||
1261 | WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL); | ||
1262 | } | ||
1263 | |||
1264 | /* Decode a single frame */ | ||
1265 | int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, | ||
1266 | enum s5p_mfc_decode_arg last_frame) | ||
1267 | { | ||
1268 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1269 | |||
1270 | WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6); | ||
1271 | WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6); | ||
1272 | |||
1273 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
1274 | /* Issue different commands to instance basing on whether it | ||
1275 | * is the last frame or not. */ | ||
1276 | switch (last_frame) { | ||
1277 | case 0: | ||
1278 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
1279 | S5P_FIMV_CH_FRAME_START_V6, NULL); | ||
1280 | break; | ||
1281 | case 1: | ||
1282 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
1283 | S5P_FIMV_CH_LAST_FRAME_V6, NULL); | ||
1284 | break; | ||
1285 | default: | ||
1286 | mfc_err("Unsupported last frame arg.\n"); | ||
1287 | return -EINVAL; | ||
1288 | } | ||
1289 | |||
1290 | mfc_debug(2, "Decoding a usual frame.\n"); | ||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) | ||
1295 | { | ||
1296 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1297 | |||
1298 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | ||
1299 | s5p_mfc_set_enc_params_h264(ctx); | ||
1300 | else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC) | ||
1301 | s5p_mfc_set_enc_params_mpeg4(ctx); | ||
1302 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) | ||
1303 | s5p_mfc_set_enc_params_h263(ctx); | ||
1304 | else { | ||
1305 | mfc_err("Unknown codec for encoding (%x).\n", | ||
1306 | ctx->codec_mode); | ||
1307 | return -EINVAL; | ||
1308 | } | ||
1309 | |||
1310 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
1311 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
1312 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); | ||
1313 | |||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx) | ||
1318 | { | ||
1319 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1320 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
1321 | struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; | ||
1322 | int i; | ||
1323 | |||
1324 | if (p_h264->aso) { | ||
1325 | for (i = 0; i < 8; i++) | ||
1326 | WRITEL(p_h264->aso_slice_order[i], | ||
1327 | S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4); | ||
1328 | } | ||
1329 | return 0; | ||
1330 | } | ||
1331 | |||
1332 | /* Encode a single frame */ | ||
1333 | int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) | ||
1334 | { | ||
1335 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1336 | |||
1337 | mfc_debug(2, "++\n"); | ||
1338 | |||
1339 | /* memory structure cur. frame */ | ||
1340 | |||
1341 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) | ||
1342 | s5p_mfc_h264_set_aso_slice_order_v6(ctx); | ||
1343 | |||
1344 | s5p_mfc_set_slice_mode(ctx); | ||
1345 | |||
1346 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | ||
1347 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | ||
1348 | S5P_FIMV_CH_FRAME_START_V6, NULL); | ||
1349 | |||
1350 | mfc_debug(2, "--\n"); | ||
1351 | |||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev) | ||
1356 | { | ||
1357 | unsigned long flags; | ||
1358 | int new_ctx; | ||
1359 | int cnt; | ||
1360 | |||
1361 | spin_lock_irqsave(&dev->condlock, flags); | ||
1362 | mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx, | ||
1363 | dev->ctx_work_bits); | ||
1364 | new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS; | ||
1365 | cnt = 0; | ||
1366 | while (!test_bit(new_ctx, &dev->ctx_work_bits)) { | ||
1367 | new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS; | ||
1368 | cnt++; | ||
1369 | if (cnt > MFC_NUM_CONTEXTS) { | ||
1370 | /* No contexts to run */ | ||
1371 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
1372 | return -EAGAIN; | ||
1373 | } | ||
1374 | } | ||
1375 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
1376 | return new_ctx; | ||
1377 | } | ||
1378 | |||
1379 | static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx) | ||
1380 | { | ||
1381 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1382 | struct s5p_mfc_buf *temp_vb; | ||
1383 | unsigned long flags; | ||
1384 | |||
1385 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1386 | |||
1387 | /* Frames are being decoded */ | ||
1388 | if (list_empty(&ctx->src_queue)) { | ||
1389 | mfc_debug(2, "No src buffers.\n"); | ||
1390 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1391 | return; | ||
1392 | } | ||
1393 | /* Get the next source buffer */ | ||
1394 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1395 | temp_vb->flags |= MFC_BUF_FLAG_USED; | ||
1396 | s5p_mfc_set_dec_stream_buffer_v6(ctx, | ||
1397 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0); | ||
1398 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1399 | |||
1400 | dev->curr_ctx = ctx->num; | ||
1401 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1402 | s5p_mfc_decode_one_frame_v6(ctx, 1); | ||
1403 | } | ||
1404 | |||
1405 | static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx) | ||
1406 | { | ||
1407 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1408 | struct s5p_mfc_buf *temp_vb; | ||
1409 | unsigned long flags; | ||
1410 | int last_frame = 0; | ||
1411 | unsigned int index; | ||
1412 | |||
1413 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1414 | |||
1415 | /* Frames are being decoded */ | ||
1416 | if (list_empty(&ctx->src_queue)) { | ||
1417 | mfc_debug(2, "No src buffers.\n"); | ||
1418 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1419 | return -EAGAIN; | ||
1420 | } | ||
1421 | /* Get the next source buffer */ | ||
1422 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1423 | temp_vb->flags |= MFC_BUF_FLAG_USED; | ||
1424 | s5p_mfc_set_dec_stream_buffer_v6(ctx, | ||
1425 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), | ||
1426 | ctx->consumed_stream, | ||
1427 | temp_vb->b->v4l2_planes[0].bytesused); | ||
1428 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1429 | |||
1430 | index = temp_vb->b->v4l2_buf.index; | ||
1431 | |||
1432 | dev->curr_ctx = ctx->num; | ||
1433 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1434 | if (temp_vb->b->v4l2_planes[0].bytesused == 0) { | ||
1435 | last_frame = 1; | ||
1436 | mfc_debug(2, "Setting ctx->state to FINISHING\n"); | ||
1437 | ctx->state = MFCINST_FINISHING; | ||
1438 | } | ||
1439 | s5p_mfc_decode_one_frame_v6(ctx, last_frame); | ||
1440 | |||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | ||
1445 | { | ||
1446 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1447 | unsigned long flags; | ||
1448 | struct s5p_mfc_buf *dst_mb; | ||
1449 | struct s5p_mfc_buf *src_mb; | ||
1450 | unsigned long src_y_addr, src_c_addr, dst_addr; | ||
1451 | /* | ||
1452 | unsigned int src_y_size, src_c_size; | ||
1453 | */ | ||
1454 | unsigned int dst_size; | ||
1455 | unsigned int index; | ||
1456 | |||
1457 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1458 | |||
1459 | if (list_empty(&ctx->src_queue)) { | ||
1460 | mfc_debug(2, "no src buffers.\n"); | ||
1461 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1462 | return -EAGAIN; | ||
1463 | } | ||
1464 | |||
1465 | if (list_empty(&ctx->dst_queue)) { | ||
1466 | mfc_debug(2, "no dst buffers.\n"); | ||
1467 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1468 | return -EAGAIN; | ||
1469 | } | ||
1470 | |||
1471 | src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1472 | src_mb->flags |= MFC_BUF_FLAG_USED; | ||
1473 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); | ||
1474 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); | ||
1475 | |||
1476 | mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr); | ||
1477 | mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr); | ||
1478 | |||
1479 | s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); | ||
1480 | |||
1481 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | ||
1482 | dst_mb->flags |= MFC_BUF_FLAG_USED; | ||
1483 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | ||
1484 | dst_size = vb2_plane_size(dst_mb->b, 0); | ||
1485 | |||
1486 | s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size); | ||
1487 | |||
1488 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1489 | |||
1490 | index = src_mb->b->v4l2_buf.index; | ||
1491 | |||
1492 | dev->curr_ctx = ctx->num; | ||
1493 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1494 | s5p_mfc_encode_one_frame_v6(ctx); | ||
1495 | |||
1496 | return 0; | ||
1497 | } | ||
1498 | |||
1499 | static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) | ||
1500 | { | ||
1501 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1502 | unsigned long flags; | ||
1503 | struct s5p_mfc_buf *temp_vb; | ||
1504 | |||
1505 | /* Initializing decoding - parsing header */ | ||
1506 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1507 | mfc_debug(2, "Preparing to init decoding.\n"); | ||
1508 | temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); | ||
1509 | mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused); | ||
1510 | s5p_mfc_set_dec_stream_buffer_v6(ctx, | ||
1511 | vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, | ||
1512 | temp_vb->b->v4l2_planes[0].bytesused); | ||
1513 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1514 | dev->curr_ctx = ctx->num; | ||
1515 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1516 | s5p_mfc_init_decode_v6(ctx); | ||
1517 | } | ||
1518 | |||
1519 | static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx) | ||
1520 | { | ||
1521 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1522 | unsigned long flags; | ||
1523 | struct s5p_mfc_buf *dst_mb; | ||
1524 | unsigned long dst_addr; | ||
1525 | unsigned int dst_size; | ||
1526 | |||
1527 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1528 | |||
1529 | dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); | ||
1530 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); | ||
1531 | dst_size = vb2_plane_size(dst_mb->b, 0); | ||
1532 | s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size); | ||
1533 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1534 | dev->curr_ctx = ctx->num; | ||
1535 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1536 | s5p_mfc_init_encode_v6(ctx); | ||
1537 | } | ||
1538 | |||
1539 | static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx) | ||
1540 | { | ||
1541 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1542 | int ret; | ||
1543 | /* Header was parsed now start processing | ||
1544 | * First set the output frame buffers | ||
1545 | * s5p_mfc_alloc_dec_buffers(ctx); */ | ||
1546 | |||
1547 | if (ctx->capture_state != QUEUE_BUFS_MMAPED) { | ||
1548 | mfc_err("It seems that not all destionation buffers were\n" | ||
1549 | "mmaped.MFC requires that all destination are mmaped\n" | ||
1550 | "before starting processing.\n"); | ||
1551 | return -EAGAIN; | ||
1552 | } | ||
1553 | |||
1554 | dev->curr_ctx = ctx->num; | ||
1555 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1556 | ret = s5p_mfc_set_dec_frame_buffer_v6(ctx); | ||
1557 | if (ret) { | ||
1558 | mfc_err("Failed to alloc frame mem.\n"); | ||
1559 | ctx->state = MFCINST_ERROR; | ||
1560 | } | ||
1561 | return ret; | ||
1562 | } | ||
1563 | |||
1564 | static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx) | ||
1565 | { | ||
1566 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1567 | int ret; | ||
1568 | |||
1569 | ret = s5p_mfc_alloc_codec_buffers_v6(ctx); | ||
1570 | if (ret) { | ||
1571 | mfc_err("Failed to allocate encoding buffers.\n"); | ||
1572 | return -ENOMEM; | ||
1573 | } | ||
1574 | |||
1575 | /* Header was generated now starting processing | ||
1576 | * First set the reference frame buffers | ||
1577 | */ | ||
1578 | if (ctx->capture_state != QUEUE_BUFS_REQUESTED) { | ||
1579 | mfc_err("It seems that destionation buffers were not\n" | ||
1580 | "requested.MFC requires that header should be generated\n" | ||
1581 | "before allocating codec buffer.\n"); | ||
1582 | return -EAGAIN; | ||
1583 | } | ||
1584 | |||
1585 | dev->curr_ctx = ctx->num; | ||
1586 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1587 | ret = s5p_mfc_set_enc_ref_buffer_v6(ctx); | ||
1588 | if (ret) { | ||
1589 | mfc_err("Failed to alloc frame mem.\n"); | ||
1590 | ctx->state = MFCINST_ERROR; | ||
1591 | } | ||
1592 | return ret; | ||
1593 | } | ||
1594 | |||
1595 | /* Try running an operation on hardware */ | ||
1596 | void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) | ||
1597 | { | ||
1598 | struct s5p_mfc_ctx *ctx; | ||
1599 | int new_ctx; | ||
1600 | unsigned int ret = 0; | ||
1601 | |||
1602 | mfc_debug(1, "Try run dev: %p\n", dev); | ||
1603 | |||
1604 | /* Check whether hardware is not running */ | ||
1605 | if (test_and_set_bit(0, &dev->hw_lock) != 0) { | ||
1606 | /* This is perfectly ok, the scheduled ctx should wait */ | ||
1607 | mfc_debug(1, "Couldn't lock HW.\n"); | ||
1608 | return; | ||
1609 | } | ||
1610 | |||
1611 | /* Choose the context to run */ | ||
1612 | new_ctx = s5p_mfc_get_new_ctx(dev); | ||
1613 | if (new_ctx < 0) { | ||
1614 | /* No contexts to run */ | ||
1615 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) { | ||
1616 | mfc_err("Failed to unlock hardware.\n"); | ||
1617 | return; | ||
1618 | } | ||
1619 | |||
1620 | mfc_debug(1, "No ctx is scheduled to be run.\n"); | ||
1621 | return; | ||
1622 | } | ||
1623 | |||
1624 | mfc_debug(1, "New context: %d\n", new_ctx); | ||
1625 | ctx = dev->ctx[new_ctx]; | ||
1626 | mfc_debug(1, "Seting new context to %p\n", ctx); | ||
1627 | /* Got context to run in ctx */ | ||
1628 | mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n", | ||
1629 | ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt); | ||
1630 | mfc_debug(1, "ctx->state=%d\n", ctx->state); | ||
1631 | /* Last frame has already been sent to MFC | ||
1632 | * Now obtaining frames from MFC buffer */ | ||
1633 | |||
1634 | s5p_mfc_clock_on(); | ||
1635 | if (ctx->type == MFCINST_DECODER) { | ||
1636 | switch (ctx->state) { | ||
1637 | case MFCINST_FINISHING: | ||
1638 | s5p_mfc_run_dec_last_frames(ctx); | ||
1639 | break; | ||
1640 | case MFCINST_RUNNING: | ||
1641 | ret = s5p_mfc_run_dec_frame(ctx); | ||
1642 | break; | ||
1643 | case MFCINST_INIT: | ||
1644 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1645 | ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, | ||
1646 | ctx); | ||
1647 | break; | ||
1648 | case MFCINST_RETURN_INST: | ||
1649 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
1650 | ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, | ||
1651 | ctx); | ||
1652 | break; | ||
1653 | case MFCINST_GOT_INST: | ||
1654 | s5p_mfc_run_init_dec(ctx); | ||
1655 | break; | ||
1656 | case MFCINST_HEAD_PARSED: | ||
1657 | ret = s5p_mfc_run_init_dec_buffers(ctx); | ||
1658 | break; | ||
1659 | case MFCINST_RES_CHANGE_INIT: | ||
1660 | s5p_mfc_run_dec_last_frames(ctx); | ||
1661 | break; | ||
1662 | case MFCINST_RES_CHANGE_FLUSH: | ||
1663 | s5p_mfc_run_dec_last_frames(ctx); | ||
1664 | break; | ||
1665 | case MFCINST_RES_CHANGE_END: | ||
1666 | mfc_debug(2, "Finished remaining frames after resolution change.\n"); | ||
1667 | ctx->capture_state = QUEUE_FREE; | ||
1668 | mfc_debug(2, "Will re-init the codec`.\n"); | ||
1669 | s5p_mfc_run_init_dec(ctx); | ||
1670 | break; | ||
1671 | default: | ||
1672 | ret = -EAGAIN; | ||
1673 | } | ||
1674 | } else if (ctx->type == MFCINST_ENCODER) { | ||
1675 | switch (ctx->state) { | ||
1676 | case MFCINST_FINISHING: | ||
1677 | case MFCINST_RUNNING: | ||
1678 | ret = s5p_mfc_run_enc_frame(ctx); | ||
1679 | break; | ||
1680 | case MFCINST_INIT: | ||
1681 | ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, | ||
1682 | ctx); | ||
1683 | break; | ||
1684 | case MFCINST_RETURN_INST: | ||
1685 | ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, | ||
1686 | ctx); | ||
1687 | break; | ||
1688 | case MFCINST_GOT_INST: | ||
1689 | s5p_mfc_run_init_enc(ctx); | ||
1690 | break; | ||
1691 | case MFCINST_HEAD_PARSED: /* Only for MFC6.x */ | ||
1692 | ret = s5p_mfc_run_init_enc_buffers(ctx); | ||
1693 | break; | ||
1694 | default: | ||
1695 | ret = -EAGAIN; | ||
1696 | } | ||
1697 | } else { | ||
1698 | mfc_err("invalid context type: %d\n", ctx->type); | ||
1699 | ret = -EAGAIN; | ||
1700 | } | ||
1701 | |||
1702 | if (ret) { | ||
1703 | /* Free hardware lock */ | ||
1704 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
1705 | mfc_err("Failed to unlock hardware.\n"); | ||
1706 | |||
1707 | /* This is in deed imporant, as no operation has been | ||
1708 | * scheduled, reduce the clock count as no one will | ||
1709 | * ever do this, because no interrupt related to this try_run | ||
1710 | * will ever come from hardware. */ | ||
1711 | s5p_mfc_clock_off(); | ||
1712 | } | ||
1713 | } | ||
1714 | |||
1715 | |||
1716 | void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) | ||
1717 | { | ||
1718 | struct s5p_mfc_buf *b; | ||
1719 | int i; | ||
1720 | |||
1721 | while (!list_empty(lh)) { | ||
1722 | b = list_entry(lh->next, struct s5p_mfc_buf, list); | ||
1723 | for (i = 0; i < b->b->num_planes; i++) | ||
1724 | vb2_set_plane_payload(b->b, i, 0); | ||
1725 | vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR); | ||
1726 | list_del(&b->list); | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1730 | void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) | ||
1731 | { | ||
1732 | mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6); | ||
1733 | mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6); | ||
1734 | } | ||
1735 | |||
1736 | void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data, | ||
1737 | unsigned int ofs) | ||
1738 | { | ||
1739 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1740 | |||
1741 | s5p_mfc_clock_on(); | ||
1742 | WRITEL(data, ofs); | ||
1743 | s5p_mfc_clock_off(); | ||
1744 | } | ||
1745 | |||
1746 | unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs) | ||
1747 | { | ||
1748 | struct s5p_mfc_dev *dev = ctx->dev; | ||
1749 | int ret; | ||
1750 | |||
1751 | s5p_mfc_clock_on(); | ||
1752 | ret = READL(ofs); | ||
1753 | s5p_mfc_clock_off(); | ||
1754 | |||
1755 | return ret; | ||
1756 | } | ||
1757 | |||
1758 | int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev) | ||
1759 | { | ||
1760 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); | ||
1761 | } | ||
1762 | |||
1763 | int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev) | ||
1764 | { | ||
1765 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); | ||
1766 | } | ||
1767 | |||
1768 | int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) | ||
1769 | { | ||
1770 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6); | ||
1771 | } | ||
1772 | |||
1773 | int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev) | ||
1774 | { | ||
1775 | return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6); | ||
1776 | } | ||
1777 | |||
1778 | int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev) | ||
1779 | { | ||
1780 | return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) & | ||
1781 | S5P_FIMV_DECODE_FRAME_MASK_V6; | ||
1782 | } | ||
1783 | |||
1784 | int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx) | ||
1785 | { | ||
1786 | return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) & | ||
1787 | S5P_FIMV_DECODE_FRAME_MASK_V6; | ||
1788 | } | ||
1789 | |||
1790 | int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev) | ||
1791 | { | ||
1792 | return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6); | ||
1793 | } | ||
1794 | |||
1795 | int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev) | ||
1796 | { | ||
1797 | return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) & | ||
1798 | S5P_FIMV_RISC2HOST_CMD_MASK; | ||
1799 | } | ||
1800 | |||
1801 | int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev) | ||
1802 | { | ||
1803 | return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6); | ||
1804 | } | ||
1805 | |||
1806 | int s5p_mfc_err_dec_v6(unsigned int err) | ||
1807 | { | ||
1808 | return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6; | ||
1809 | } | ||
1810 | |||
1811 | int s5p_mfc_err_dspl_v6(unsigned int err) | ||
1812 | { | ||
1813 | return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6; | ||
1814 | } | ||
1815 | |||
1816 | int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev) | ||
1817 | { | ||
1818 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6); | ||
1819 | } | ||
1820 | |||
1821 | int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev) | ||
1822 | { | ||
1823 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6); | ||
1824 | } | ||
1825 | |||
1826 | int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev) | ||
1827 | { | ||
1828 | return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6); | ||
1829 | } | ||
1830 | |||
1831 | int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev) | ||
1832 | { | ||
1833 | return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6); | ||
1834 | } | ||
1835 | |||
1836 | int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev) | ||
1837 | { | ||
1838 | return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6); | ||
1839 | } | ||
1840 | |||
1841 | int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev) | ||
1842 | { | ||
1843 | return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6); | ||
1844 | } | ||
1845 | |||
1846 | int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev) | ||
1847 | { | ||
1848 | return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6); | ||
1849 | } | ||
1850 | |||
1851 | int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev) | ||
1852 | { | ||
1853 | return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6); | ||
1854 | } | ||
1855 | |||
1856 | int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev) | ||
1857 | { | ||
1858 | return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6); | ||
1859 | } | ||
1860 | |||
1861 | int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx) | ||
1862 | { | ||
1863 | return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6); | ||
1864 | } | ||
1865 | |||
1866 | int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev) | ||
1867 | { | ||
1868 | return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6); | ||
1869 | } | ||
1870 | |||
1871 | int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev) | ||
1872 | { | ||
1873 | return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6); | ||
1874 | } | ||
1875 | |||
1876 | unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx) | ||
1877 | { | ||
1878 | return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6); | ||
1879 | } | ||
1880 | |||
1881 | unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx) | ||
1882 | { | ||
1883 | return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6); | ||
1884 | } | ||
1885 | |||
1886 | unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx) | ||
1887 | { | ||
1888 | return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6); | ||
1889 | } | ||
1890 | |||
1891 | unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx) | ||
1892 | { | ||
1893 | return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6); | ||
1894 | } | ||
1895 | |||
1896 | /* Initialize opr function pointers for MFC v6 */ | ||
1897 | static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = { | ||
1898 | .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6, | ||
1899 | .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6, | ||
1900 | .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6, | ||
1901 | .release_codec_buffers = s5p_mfc_release_codec_buffers_v6, | ||
1902 | .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6, | ||
1903 | .release_instance_buffer = s5p_mfc_release_instance_buffer_v6, | ||
1904 | .alloc_dev_context_buffer = | ||
1905 | s5p_mfc_alloc_dev_context_buffer_v6, | ||
1906 | .release_dev_context_buffer = | ||
1907 | s5p_mfc_release_dev_context_buffer_v6, | ||
1908 | .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6, | ||
1909 | .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6, | ||
1910 | .set_dec_stream_buffer = s5p_mfc_set_dec_stream_buffer_v6, | ||
1911 | .set_dec_frame_buffer = s5p_mfc_set_dec_frame_buffer_v6, | ||
1912 | .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6, | ||
1913 | .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6, | ||
1914 | .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6, | ||
1915 | .set_enc_ref_buffer = s5p_mfc_set_enc_ref_buffer_v6, | ||
1916 | .init_decode = s5p_mfc_init_decode_v6, | ||
1917 | .init_encode = s5p_mfc_init_encode_v6, | ||
1918 | .encode_one_frame = s5p_mfc_encode_one_frame_v6, | ||
1919 | .try_run = s5p_mfc_try_run_v6, | ||
1920 | .cleanup_queue = s5p_mfc_cleanup_queue_v6, | ||
1921 | .clear_int_flags = s5p_mfc_clear_int_flags_v6, | ||
1922 | .write_info = s5p_mfc_write_info_v6, | ||
1923 | .read_info = s5p_mfc_read_info_v6, | ||
1924 | .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6, | ||
1925 | .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6, | ||
1926 | .get_dspl_status = s5p_mfc_get_dspl_status_v6, | ||
1927 | .get_dec_status = s5p_mfc_get_dec_status_v6, | ||
1928 | .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6, | ||
1929 | .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6, | ||
1930 | .get_consumed_stream = s5p_mfc_get_consumed_stream_v6, | ||
1931 | .get_int_reason = s5p_mfc_get_int_reason_v6, | ||
1932 | .get_int_err = s5p_mfc_get_int_err_v6, | ||
1933 | .err_dec = s5p_mfc_err_dec_v6, | ||
1934 | .err_dspl = s5p_mfc_err_dspl_v6, | ||
1935 | .get_img_width = s5p_mfc_get_img_width_v6, | ||
1936 | .get_img_height = s5p_mfc_get_img_height_v6, | ||
1937 | .get_dpb_count = s5p_mfc_get_dpb_count_v6, | ||
1938 | .get_mv_count = s5p_mfc_get_mv_count_v6, | ||
1939 | .get_inst_no = s5p_mfc_get_inst_no_v6, | ||
1940 | .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6, | ||
1941 | .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6, | ||
1942 | .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6, | ||
1943 | .get_enc_pic_count = s5p_mfc_get_enc_pic_count_v6, | ||
1944 | .get_sei_avail_status = s5p_mfc_get_sei_avail_status_v6, | ||
1945 | .get_mvc_num_views = s5p_mfc_get_mvc_num_views_v6, | ||
1946 | .get_mvc_view_id = s5p_mfc_get_mvc_view_id_v6, | ||
1947 | .get_pic_type_top = s5p_mfc_get_pic_type_top_v6, | ||
1948 | .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6, | ||
1949 | .get_crop_info_h = s5p_mfc_get_crop_info_h_v6, | ||
1950 | .get_crop_info_v = s5p_mfc_get_crop_info_v_v6, | ||
1951 | }; | ||
1952 | |||
1953 | struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void) | ||
1954 | { | ||
1955 | return &s5p_mfc_ops_v6; | ||
1956 | } | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h new file mode 100644 index 000000000000..ab164efa127e --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h | ||
3 | * | ||
4 | * Header file for Samsung MFC (Multi Function Codec - FIMV) driver | ||
5 | * Contains declarations of hw related functions. | ||
6 | * | ||
7 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
8 | * http://www.samsung.com/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef S5P_MFC_OPR_V6_H_ | ||
16 | #define S5P_MFC_OPR_V6_H_ | ||
17 | |||
18 | #include "s5p_mfc_common.h" | ||
19 | #include "s5p_mfc_opr.h" | ||
20 | |||
21 | #define MFC_CTRL_MODE_CUSTOM MFC_CTRL_MODE_SFR | ||
22 | |||
23 | #define MB_WIDTH(x_size) DIV_ROUND_UP(x_size, 16) | ||
24 | #define MB_HEIGHT(y_size) DIV_ROUND_UP(y_size, 16) | ||
25 | #define S5P_MFC_DEC_MV_SIZE_V6(x, y) (MB_WIDTH(x) * \ | ||
26 | (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128) | ||
27 | |||
28 | /* Definition */ | ||
29 | #define ENC_MULTI_SLICE_MB_MAX ((1 << 30) - 1) | ||
30 | #define ENC_MULTI_SLICE_BIT_MIN 2800 | ||
31 | #define ENC_INTRA_REFRESH_MB_MAX ((1 << 18) - 1) | ||
32 | #define ENC_VBV_BUF_SIZE_MAX ((1 << 30) - 1) | ||
33 | #define ENC_H264_LOOP_FILTER_AB_MIN -12 | ||
34 | #define ENC_H264_LOOP_FILTER_AB_MAX 12 | ||
35 | #define ENC_H264_RC_FRAME_RATE_MAX ((1 << 16) - 1) | ||
36 | #define ENC_H263_RC_FRAME_RATE_MAX ((1 << 16) - 1) | ||
37 | #define ENC_H264_PROFILE_MAX 3 | ||
38 | #define ENC_H264_LEVEL_MAX 42 | ||
39 | #define ENC_MPEG4_VOP_TIME_RES_MAX ((1 << 16) - 1) | ||
40 | #define FRAME_DELTA_H264_H263 1 | ||
41 | #define TIGHT_CBR_MAX 10 | ||
42 | |||
43 | /* Definitions for shared memory compatibility */ | ||
44 | #define PIC_TIME_TOP_V6 S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 | ||
45 | #define PIC_TIME_BOT_V6 S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 | ||
46 | #define CROP_INFO_H_V6 S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 | ||
47 | #define CROP_INFO_V_V6 S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 | ||
48 | |||
49 | struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void); | ||
50 | #endif /* S5P_MFC_OPR_V6_H_ */ | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c index 0503d14ac94e..367db7552289 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include "s5p_mfc_debug.h" | 20 | #include "s5p_mfc_debug.h" |
21 | #include "s5p_mfc_pm.h" | 21 | #include "s5p_mfc_pm.h" |
22 | 22 | ||
23 | #define MFC_CLKNAME "sclk_mfc" | ||
24 | #define MFC_GATE_CLK_NAME "mfc" | 23 | #define MFC_GATE_CLK_NAME "mfc" |
25 | 24 | ||
26 | #define CLK_DEBUG | 25 | #define CLK_DEBUG |
@@ -51,7 +50,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
51 | goto err_p_ip_clk; | 50 | goto err_p_ip_clk; |
52 | } | 51 | } |
53 | 52 | ||
54 | pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME); | 53 | pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name); |
55 | if (IS_ERR(pm->clock)) { | 54 | if (IS_ERR(pm->clock)) { |
56 | mfc_err("Failed to get MFC clock\n"); | 55 | mfc_err("Failed to get MFC clock\n"); |
57 | ret = PTR_ERR(pm->clock); | 56 | ret = PTR_ERR(pm->clock); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c deleted file mode 100644 index b5933d233a4b..000000000000 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifdef CONFIG_ARCH_EXYNOS4 | ||
14 | #include <linux/dma-mapping.h> | ||
15 | #endif | ||
16 | #include <linux/io.h> | ||
17 | #include "s5p_mfc_common.h" | ||
18 | #include "s5p_mfc_debug.h" | ||
19 | |||
20 | int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx) | ||
21 | { | ||
22 | struct s5p_mfc_dev *dev = ctx->dev; | ||
23 | void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | ||
24 | |||
25 | ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx, | ||
26 | SHARED_BUF_SIZE); | ||
27 | if (IS_ERR(ctx->shm_alloc)) { | ||
28 | mfc_err("failed to allocate shared memory\n"); | ||
29 | return PTR_ERR(ctx->shm_alloc); | ||
30 | } | ||
31 | /* shm_ofs only keeps the offset from base (port a) */ | ||
32 | ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc) | ||
33 | - dev->bank1; | ||
34 | BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | ||
35 | ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc); | ||
36 | if (!ctx->shm) { | ||
37 | vb2_dma_contig_memops.put(ctx->shm_alloc); | ||
38 | ctx->shm_ofs = 0; | ||
39 | ctx->shm_alloc = NULL; | ||
40 | mfc_err("failed to virt addr of shared memory\n"); | ||
41 | return -ENOMEM; | ||
42 | } | ||
43 | memset((void *)ctx->shm, 0, SHARED_BUF_SIZE); | ||
44 | wmb(); | ||
45 | return 0; | ||
46 | } | ||
47 | |||
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 403d7f17bfab..9fd9d1c5b218 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c | |||
@@ -1376,6 +1376,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1376 | __u32 pixfmt = pix->pixelformat; | 1376 | __u32 pixfmt = pix->pixelformat; |
1377 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 1377 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
1378 | struct mx2_camera_dev *pcdev = ici->priv; | 1378 | struct mx2_camera_dev *pcdev = ici->priv; |
1379 | struct mx2_fmt_cfg *emma_prp; | ||
1379 | unsigned int width_limit; | 1380 | unsigned int width_limit; |
1380 | int ret; | 1381 | int ret; |
1381 | 1382 | ||
@@ -1438,12 +1439,11 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1438 | __func__, pcdev->s_width, pcdev->s_height); | 1439 | __func__, pcdev->s_width, pcdev->s_height); |
1439 | 1440 | ||
1440 | /* If the sensor does not support image size try PrP resizing */ | 1441 | /* If the sensor does not support image size try PrP resizing */ |
1441 | pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, | 1442 | emma_prp = mx27_emma_prp_get_format(xlate->code, |
1442 | xlate->host_fmt->fourcc); | 1443 | xlate->host_fmt->fourcc); |
1443 | 1444 | ||
1444 | memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); | ||
1445 | if ((mf.width != pix->width || mf.height != pix->height) && | 1445 | if ((mf.width != pix->width || mf.height != pix->height) && |
1446 | pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { | 1446 | emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { |
1447 | if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) | 1447 | if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) |
1448 | dev_dbg(icd->parent, "%s: can't resize\n", __func__); | 1448 | dev_dbg(icd->parent, "%s: can't resize\n", __func__); |
1449 | } | 1449 | } |
@@ -1655,6 +1655,7 @@ static int __devinit mx27_camera_emma_init(struct platform_device *pdev) | |||
1655 | irq_emma = platform_get_irq(pdev, 1); | 1655 | irq_emma = platform_get_irq(pdev, 1); |
1656 | if (!res_emma || !irq_emma) { | 1656 | if (!res_emma || !irq_emma) { |
1657 | dev_err(pcdev->dev, "no EMMA resources\n"); | 1657 | dev_err(pcdev->dev, "no EMMA resources\n"); |
1658 | err = -ENODEV; | ||
1658 | goto out; | 1659 | goto out; |
1659 | } | 1660 | } |
1660 | 1661 | ||
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 3be92944f8e7..d3f0b84e2d70 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -950,11 +950,11 @@ static int soc_camera_s_selection(struct file *file, void *fh, | |||
950 | 950 | ||
951 | /* In all these cases cropping emulation will not help */ | 951 | /* In all these cases cropping emulation will not help */ |
952 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | 952 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || |
953 | (s->target != V4L2_SEL_TGT_COMPOSE_ACTIVE && | 953 | (s->target != V4L2_SEL_TGT_COMPOSE && |
954 | s->target != V4L2_SEL_TGT_CROP_ACTIVE)) | 954 | s->target != V4L2_SEL_TGT_CROP)) |
955 | return -EINVAL; | 955 | return -EINVAL; |
956 | 956 | ||
957 | if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) { | 957 | if (s->target == V4L2_SEL_TGT_COMPOSE) { |
958 | /* No output size change during a running capture! */ | 958 | /* No output size change during a running capture! */ |
959 | if (is_streaming(ici, icd) && | 959 | if (is_streaming(ici, icd) && |
960 | (icd->user_width != s->r.width || | 960 | (icd->user_width != s->r.width || |
@@ -974,7 +974,7 @@ static int soc_camera_s_selection(struct file *file, void *fh, | |||
974 | 974 | ||
975 | ret = ici->ops->set_selection(icd, s); | 975 | ret = ici->ops->set_selection(icd, s); |
976 | if (!ret && | 976 | if (!ret && |
977 | s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) { | 977 | s->target == V4L2_SEL_TGT_COMPOSE) { |
978 | icd->user_width = s->r.width; | 978 | icd->user_width = s->r.width; |
979 | icd->user_height = s->r.height; | 979 | icd->user_height = s->r.height; |
980 | if (!icd->streamer) | 980 | if (!icd->streamer) |
@@ -1184,7 +1184,8 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1184 | sd->grp_id = soc_camera_grp_id(icd); | 1184 | sd->grp_id = soc_camera_grp_id(icd); |
1185 | v4l2_set_subdev_hostdata(sd, icd); | 1185 | v4l2_set_subdev_hostdata(sd, icd); |
1186 | 1186 | ||
1187 | if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL)) | 1187 | ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL); |
1188 | if (ret < 0) | ||
1188 | goto ectrl; | 1189 | goto ectrl; |
1189 | 1190 | ||
1190 | /* At this point client .probe() should have run already */ | 1191 | /* At this point client .probe() should have run already */ |
@@ -1529,12 +1530,11 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | |||
1529 | { | 1530 | { |
1530 | struct soc_camera_link *icl = pdev->dev.platform_data; | 1531 | struct soc_camera_link *icl = pdev->dev.platform_data; |
1531 | struct soc_camera_device *icd; | 1532 | struct soc_camera_device *icd; |
1532 | int ret; | ||
1533 | 1533 | ||
1534 | if (!icl) | 1534 | if (!icl) |
1535 | return -EINVAL; | 1535 | return -EINVAL; |
1536 | 1536 | ||
1537 | icd = kzalloc(sizeof(*icd), GFP_KERNEL); | 1537 | icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL); |
1538 | if (!icd) | 1538 | if (!icd) |
1539 | return -ENOMEM; | 1539 | return -ENOMEM; |
1540 | 1540 | ||
@@ -1543,19 +1543,10 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | |||
1543 | icd->pdev = &pdev->dev; | 1543 | icd->pdev = &pdev->dev; |
1544 | platform_set_drvdata(pdev, icd); | 1544 | platform_set_drvdata(pdev, icd); |
1545 | 1545 | ||
1546 | ret = soc_camera_device_register(icd); | ||
1547 | if (ret < 0) | ||
1548 | goto escdevreg; | ||
1549 | |||
1550 | icd->user_width = DEFAULT_WIDTH; | 1546 | icd->user_width = DEFAULT_WIDTH; |
1551 | icd->user_height = DEFAULT_HEIGHT; | 1547 | icd->user_height = DEFAULT_HEIGHT; |
1552 | 1548 | ||
1553 | return 0; | 1549 | return soc_camera_device_register(icd); |
1554 | |||
1555 | escdevreg: | ||
1556 | kfree(icd); | ||
1557 | |||
1558 | return ret; | ||
1559 | } | 1550 | } |
1560 | 1551 | ||
1561 | /* | 1552 | /* |
@@ -1572,8 +1563,6 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) | |||
1572 | 1563 | ||
1573 | list_del(&icd->list); | 1564 | list_del(&icd->list); |
1574 | 1565 | ||
1575 | kfree(icd); | ||
1576 | |||
1577 | return 0; | 1566 | return 0; |
1578 | } | 1567 | } |
1579 | 1568 | ||
@@ -1586,18 +1575,7 @@ static struct platform_driver __refdata soc_camera_pdrv = { | |||
1586 | }, | 1575 | }, |
1587 | }; | 1576 | }; |
1588 | 1577 | ||
1589 | static int __init soc_camera_init(void) | 1578 | module_platform_driver(soc_camera_pdrv); |
1590 | { | ||
1591 | return platform_driver_register(&soc_camera_pdrv); | ||
1592 | } | ||
1593 | |||
1594 | static void __exit soc_camera_exit(void) | ||
1595 | { | ||
1596 | platform_driver_unregister(&soc_camera_pdrv); | ||
1597 | } | ||
1598 | |||
1599 | module_init(soc_camera_init); | ||
1600 | module_exit(soc_camera_exit); | ||
1601 | 1579 | ||
1602 | MODULE_DESCRIPTION("Image capture bus driver"); | 1580 | MODULE_DESCRIPTION("Image capture bus driver"); |
1603 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); | 1581 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); |
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index e5024cfd27a7..4ef55ec8045e 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c | |||
@@ -308,7 +308,7 @@ static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) | |||
308 | READCHAN_BLERD) >> 10; | 308 | READCHAN_BLERD) >> 10; |
309 | rds = radio->registers[RDSD]; | 309 | rds = radio->registers[RDSD]; |
310 | break; | 310 | break; |
311 | }; | 311 | } |
312 | 312 | ||
313 | /* Fill the V4L2 RDS buffer */ | 313 | /* Fill the V4L2 RDS buffer */ |
314 | put_unaligned_le16(rds, &tmpbuf); | 314 | put_unaligned_le16(rds, &tmpbuf); |
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index be076f7181e7..62f3edec39bc 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c | |||
@@ -446,7 +446,7 @@ static void si470x_int_in_callback(struct urb *urb) | |||
446 | READCHAN_BLERD) >> 10; | 446 | READCHAN_BLERD) >> 10; |
447 | rds = radio->registers[RDSD]; | 447 | rds = radio->registers[RDSD]; |
448 | break; | 448 | break; |
449 | }; | 449 | } |
450 | 450 | ||
451 | /* Fill the V4L2 RDS buffer */ | 451 | /* Fill the V4L2 RDS buffer */ |
452 | put_unaligned_le16(rds, &tmpbuf); | 452 | put_unaligned_le16(rds, &tmpbuf); |
diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index a9e6d17015ef..e3079c142c5f 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c | |||
@@ -1009,7 +1009,7 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, | |||
1009 | 1009 | ||
1010 | default: | 1010 | default: |
1011 | rval = -EINVAL; | 1011 | rval = -EINVAL; |
1012 | }; | 1012 | } |
1013 | 1013 | ||
1014 | return rval; | 1014 | return rval; |
1015 | } | 1015 | } |
@@ -1081,7 +1081,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev, | |||
1081 | default: | 1081 | default: |
1082 | rval = -EINVAL; | 1082 | rval = -EINVAL; |
1083 | break; | 1083 | break; |
1084 | }; | 1084 | } |
1085 | 1085 | ||
1086 | exit: | 1086 | exit: |
1087 | return rval; | 1087 | return rval; |
@@ -1130,7 +1130,7 @@ static int si4713_write_econtrol_tune(struct si4713_device *sdev, | |||
1130 | default: | 1130 | default: |
1131 | rval = -EINVAL; | 1131 | rval = -EINVAL; |
1132 | goto unlock; | 1132 | goto unlock; |
1133 | }; | 1133 | } |
1134 | 1134 | ||
1135 | if (sdev->power_state) | 1135 | if (sdev->power_state) |
1136 | rval = si4713_tx_tune_power(sdev, power, antcap); | 1136 | rval = si4713_tx_tune_power(sdev, power, antcap); |
@@ -1420,7 +1420,7 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev, | |||
1420 | default: | 1420 | default: |
1421 | rval = -EINVAL; | 1421 | rval = -EINVAL; |
1422 | break; | 1422 | break; |
1423 | }; | 1423 | } |
1424 | 1424 | ||
1425 | exit: | 1425 | exit: |
1426 | return rval; | 1426 | return rval; |
@@ -1473,7 +1473,7 @@ static int si4713_read_econtrol_tune(struct si4713_device *sdev, | |||
1473 | break; | 1473 | break; |
1474 | default: | 1474 | default: |
1475 | rval = -EINVAL; | 1475 | rval = -EINVAL; |
1476 | }; | 1476 | } |
1477 | 1477 | ||
1478 | unlock: | 1478 | unlock: |
1479 | mutex_unlock(&sdev->mutex); | 1479 | mutex_unlock(&sdev->mutex); |
@@ -1698,7 +1698,7 @@ static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | |||
1698 | default: | 1698 | default: |
1699 | rval = -EINVAL; | 1699 | rval = -EINVAL; |
1700 | break; | 1700 | break; |
1701 | }; | 1701 | } |
1702 | 1702 | ||
1703 | return rval; | 1703 | return rval; |
1704 | } | 1704 | } |
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 647dd951b0e8..d05ac15b5de4 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c | |||
@@ -881,10 +881,13 @@ static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask) | |||
881 | static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier) | 881 | static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier) |
882 | { | 882 | { |
883 | struct ene_device *dev = rdev->priv; | 883 | struct ene_device *dev = rdev->priv; |
884 | u32 period = 2000000 / carrier; | 884 | u32 period; |
885 | 885 | ||
886 | dbg("TX: attempt to set tx carrier to %d kHz", carrier); | 886 | dbg("TX: attempt to set tx carrier to %d kHz", carrier); |
887 | if (carrier == 0) | ||
888 | return -EINVAL; | ||
887 | 889 | ||
890 | period = 2000000 / carrier; | ||
888 | if (period && (period > ENE_CIRMOD_PRD_MAX || | 891 | if (period && (period > ENE_CIRMOD_PRD_MAX || |
889 | period < ENE_CIRMOD_PRD_MIN)) { | 892 | period < ENE_CIRMOD_PRD_MIN)) { |
890 | 893 | ||
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index 1e4c68a5cecf..51d7057aca04 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <media/rc-core.h> | 28 | #include <media/rc-core.h> |
29 | 29 | ||
30 | #define DRIVER_NAME "iguanair" | 30 | #define DRIVER_NAME "iguanair" |
31 | #define BUF_SIZE 152 | ||
31 | 32 | ||
32 | struct iguanair { | 33 | struct iguanair { |
33 | struct rc_dev *rc; | 34 | struct rc_dev *rc; |
@@ -35,26 +36,23 @@ struct iguanair { | |||
35 | struct device *dev; | 36 | struct device *dev; |
36 | struct usb_device *udev; | 37 | struct usb_device *udev; |
37 | 38 | ||
38 | int pipe_out; | ||
39 | uint16_t version; | 39 | uint16_t version; |
40 | uint8_t bufsize; | 40 | uint8_t bufsize; |
41 | uint8_t cycle_overhead; | ||
41 | 42 | ||
42 | struct mutex lock; | 43 | struct mutex lock; |
43 | 44 | ||
44 | /* receiver support */ | 45 | /* receiver support */ |
45 | bool receiver_on; | 46 | bool receiver_on; |
46 | dma_addr_t dma_in; | 47 | dma_addr_t dma_in, dma_out; |
47 | uint8_t *buf_in; | 48 | uint8_t *buf_in; |
48 | struct urb *urb_in; | 49 | struct urb *urb_in, *urb_out; |
49 | struct completion completion; | 50 | struct completion completion; |
50 | 51 | ||
51 | /* transmit support */ | 52 | /* transmit support */ |
52 | bool tx_overflow; | 53 | bool tx_overflow; |
53 | uint32_t carrier; | 54 | uint32_t carrier; |
54 | uint8_t cycle_overhead; | 55 | struct send_packet *packet; |
55 | uint8_t channels; | ||
56 | uint8_t busy4; | ||
57 | uint8_t busy7; | ||
58 | 56 | ||
59 | char name[64]; | 57 | char name[64]; |
60 | char phys[64]; | 58 | char phys[64]; |
@@ -73,7 +71,8 @@ struct iguanair { | |||
73 | #define DIR_IN 0xdc | 71 | #define DIR_IN 0xdc |
74 | #define DIR_OUT 0xcd | 72 | #define DIR_OUT 0xcd |
75 | 73 | ||
76 | #define MAX_PACKET_SIZE 8u | 74 | #define MAX_IN_PACKET 8u |
75 | #define MAX_OUT_PACKET (sizeof(struct send_packet) + BUF_SIZE) | ||
77 | #define TIMEOUT 1000 | 76 | #define TIMEOUT 1000 |
78 | #define RX_RESOLUTION 21333 | 77 | #define RX_RESOLUTION 21333 |
79 | 78 | ||
@@ -191,20 +190,25 @@ static void iguanair_rx(struct urb *urb) | |||
191 | dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc); | 190 | dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc); |
192 | } | 191 | } |
193 | 192 | ||
194 | static int iguanair_send(struct iguanair *ir, void *data, unsigned size) | 193 | static void iguanair_irq_out(struct urb *urb) |
195 | { | 194 | { |
196 | int rc, transferred; | 195 | struct iguanair *ir = urb->context; |
196 | |||
197 | if (urb->status) | ||
198 | dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status); | ||
199 | } | ||
200 | |||
201 | static int iguanair_send(struct iguanair *ir, unsigned size) | ||
202 | { | ||
203 | int rc; | ||
197 | 204 | ||
198 | INIT_COMPLETION(ir->completion); | 205 | INIT_COMPLETION(ir->completion); |
199 | 206 | ||
200 | rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size, | 207 | ir->urb_out->transfer_buffer_length = size; |
201 | &transferred, TIMEOUT); | 208 | rc = usb_submit_urb(ir->urb_out, GFP_KERNEL); |
202 | if (rc) | 209 | if (rc) |
203 | return rc; | 210 | return rc; |
204 | 211 | ||
205 | if (transferred != size) | ||
206 | return -EIO; | ||
207 | |||
208 | if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0) | 212 | if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0) |
209 | return -ETIMEDOUT; | 213 | return -ETIMEDOUT; |
210 | 214 | ||
@@ -213,14 +217,13 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size) | |||
213 | 217 | ||
214 | static int iguanair_get_features(struct iguanair *ir) | 218 | static int iguanair_get_features(struct iguanair *ir) |
215 | { | 219 | { |
216 | struct packet packet; | ||
217 | int rc; | 220 | int rc; |
218 | 221 | ||
219 | packet.start = 0; | 222 | ir->packet->header.start = 0; |
220 | packet.direction = DIR_OUT; | 223 | ir->packet->header.direction = DIR_OUT; |
221 | packet.cmd = CMD_GET_VERSION; | 224 | ir->packet->header.cmd = CMD_GET_VERSION; |
222 | 225 | ||
223 | rc = iguanair_send(ir, &packet, sizeof(packet)); | 226 | rc = iguanair_send(ir, sizeof(ir->packet->header)); |
224 | if (rc) { | 227 | if (rc) { |
225 | dev_info(ir->dev, "failed to get version\n"); | 228 | dev_info(ir->dev, "failed to get version\n"); |
226 | goto out; | 229 | goto out; |
@@ -235,17 +238,23 @@ static int iguanair_get_features(struct iguanair *ir) | |||
235 | ir->bufsize = 150; | 238 | ir->bufsize = 150; |
236 | ir->cycle_overhead = 65; | 239 | ir->cycle_overhead = 65; |
237 | 240 | ||
238 | packet.cmd = CMD_GET_BUFSIZE; | 241 | ir->packet->header.cmd = CMD_GET_BUFSIZE; |
239 | 242 | ||
240 | rc = iguanair_send(ir, &packet, sizeof(packet)); | 243 | rc = iguanair_send(ir, sizeof(ir->packet->header)); |
241 | if (rc) { | 244 | if (rc) { |
242 | dev_info(ir->dev, "failed to get buffer size\n"); | 245 | dev_info(ir->dev, "failed to get buffer size\n"); |
243 | goto out; | 246 | goto out; |
244 | } | 247 | } |
245 | 248 | ||
246 | packet.cmd = CMD_GET_FEATURES; | 249 | if (ir->bufsize > BUF_SIZE) { |
250 | dev_info(ir->dev, "buffer size %u larger than expected\n", | ||
251 | ir->bufsize); | ||
252 | ir->bufsize = BUF_SIZE; | ||
253 | } | ||
254 | |||
255 | ir->packet->header.cmd = CMD_GET_FEATURES; | ||
247 | 256 | ||
248 | rc = iguanair_send(ir, &packet, sizeof(packet)); | 257 | rc = iguanair_send(ir, sizeof(ir->packet->header)); |
249 | if (rc) { | 258 | if (rc) { |
250 | dev_info(ir->dev, "failed to get features\n"); | 259 | dev_info(ir->dev, "failed to get features\n"); |
251 | goto out; | 260 | goto out; |
@@ -257,13 +266,18 @@ out: | |||
257 | 266 | ||
258 | static int iguanair_receiver(struct iguanair *ir, bool enable) | 267 | static int iguanair_receiver(struct iguanair *ir, bool enable) |
259 | { | 268 | { |
260 | struct packet packet = { 0, DIR_OUT, enable ? | 269 | int rc; |
261 | CMD_RECEIVER_ON : CMD_RECEIVER_OFF }; | 270 | |
271 | ir->packet->header.start = 0; | ||
272 | ir->packet->header.direction = DIR_OUT; | ||
273 | ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF; | ||
262 | 274 | ||
263 | if (enable) | 275 | if (enable) |
264 | ir_raw_event_reset(ir->rc); | 276 | ir_raw_event_reset(ir->rc); |
265 | 277 | ||
266 | return iguanair_send(ir, &packet, sizeof(packet)); | 278 | rc = iguanair_send(ir, sizeof(ir->packet->header)); |
279 | |||
280 | return rc; | ||
267 | } | 281 | } |
268 | 282 | ||
269 | /* | 283 | /* |
@@ -308,8 +322,8 @@ static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier) | |||
308 | fours = (cycles - sevens * 7) / 4; | 322 | fours = (cycles - sevens * 7) / 4; |
309 | 323 | ||
310 | /* magic happens here */ | 324 | /* magic happens here */ |
311 | ir->busy7 = (4 - sevens) * 2; | 325 | ir->packet->busy7 = (4 - sevens) * 2; |
312 | ir->busy4 = 110 - fours; | 326 | ir->packet->busy4 = 110 - fours; |
313 | } | 327 | } |
314 | 328 | ||
315 | mutex_unlock(&ir->lock); | 329 | mutex_unlock(&ir->lock); |
@@ -325,7 +339,7 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask) | |||
325 | return 4; | 339 | return 4; |
326 | 340 | ||
327 | mutex_lock(&ir->lock); | 341 | mutex_lock(&ir->lock); |
328 | ir->channels = mask; | 342 | ir->packet->channels = mask << 4; |
329 | mutex_unlock(&ir->lock); | 343 | mutex_unlock(&ir->lock); |
330 | 344 | ||
331 | return 0; | 345 | return 0; |
@@ -337,16 +351,9 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) | |||
337 | uint8_t space; | 351 | uint8_t space; |
338 | unsigned i, size, periods, bytes; | 352 | unsigned i, size, periods, bytes; |
339 | int rc; | 353 | int rc; |
340 | struct send_packet *packet; | ||
341 | 354 | ||
342 | mutex_lock(&ir->lock); | 355 | mutex_lock(&ir->lock); |
343 | 356 | ||
344 | packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL); | ||
345 | if (!packet) { | ||
346 | rc = -ENOMEM; | ||
347 | goto out; | ||
348 | } | ||
349 | |||
350 | /* convert from us to carrier periods */ | 357 | /* convert from us to carrier periods */ |
351 | for (i = space = size = 0; i < count; i++) { | 358 | for (i = space = size = 0; i < count; i++) { |
352 | periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); | 359 | periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); |
@@ -356,11 +363,11 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) | |||
356 | break; | 363 | break; |
357 | } | 364 | } |
358 | while (periods > 127) { | 365 | while (periods > 127) { |
359 | packet->payload[size++] = 127 | space; | 366 | ir->packet->payload[size++] = 127 | space; |
360 | periods -= 127; | 367 | periods -= 127; |
361 | } | 368 | } |
362 | 369 | ||
363 | packet->payload[size++] = periods | space; | 370 | ir->packet->payload[size++] = periods | space; |
364 | space ^= 0x80; | 371 | space ^= 0x80; |
365 | } | 372 | } |
366 | 373 | ||
@@ -369,36 +376,19 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) | |||
369 | goto out; | 376 | goto out; |
370 | } | 377 | } |
371 | 378 | ||
372 | packet->header.start = 0; | 379 | ir->packet->header.start = 0; |
373 | packet->header.direction = DIR_OUT; | 380 | ir->packet->header.direction = DIR_OUT; |
374 | packet->header.cmd = CMD_SEND; | 381 | ir->packet->header.cmd = CMD_SEND; |
375 | packet->length = size; | 382 | ir->packet->length = size; |
376 | packet->channels = ir->channels << 4; | ||
377 | packet->busy7 = ir->busy7; | ||
378 | packet->busy4 = ir->busy4; | ||
379 | |||
380 | if (ir->receiver_on) { | ||
381 | rc = iguanair_receiver(ir, false); | ||
382 | if (rc) { | ||
383 | dev_warn(ir->dev, "disable receiver before transmit failed\n"); | ||
384 | goto out; | ||
385 | } | ||
386 | } | ||
387 | 383 | ||
388 | ir->tx_overflow = false; | 384 | ir->tx_overflow = false; |
389 | 385 | ||
390 | rc = iguanair_send(ir, packet, size + 8); | 386 | rc = iguanair_send(ir, sizeof(*ir->packet) + size); |
391 | 387 | ||
392 | if (rc == 0 && ir->tx_overflow) | 388 | if (rc == 0 && ir->tx_overflow) |
393 | rc = -EOVERFLOW; | 389 | rc = -EOVERFLOW; |
394 | 390 | ||
395 | if (ir->receiver_on) { | ||
396 | if (iguanair_receiver(ir, true)) | ||
397 | dev_warn(ir->dev, "re-enable receiver after transmit failed\n"); | ||
398 | } | ||
399 | |||
400 | out: | 391 | out: |
401 | kfree(packet); | ||
402 | mutex_unlock(&ir->lock); | 392 | mutex_unlock(&ir->lock); |
403 | 393 | ||
404 | return rc ? rc : count; | 394 | return rc ? rc : count; |
@@ -411,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev) | |||
411 | 401 | ||
412 | mutex_lock(&ir->lock); | 402 | mutex_lock(&ir->lock); |
413 | 403 | ||
414 | BUG_ON(ir->receiver_on); | ||
415 | |||
416 | rc = iguanair_receiver(ir, true); | 404 | rc = iguanair_receiver(ir, true); |
417 | if (rc == 0) | 405 | if (rc == 0) |
418 | ir->receiver_on = true; | 406 | ir->receiver_on = true; |
@@ -443,7 +431,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf, | |||
443 | struct usb_device *udev = interface_to_usbdev(intf); | 431 | struct usb_device *udev = interface_to_usbdev(intf); |
444 | struct iguanair *ir; | 432 | struct iguanair *ir; |
445 | struct rc_dev *rc; | 433 | struct rc_dev *rc; |
446 | int ret, pipein; | 434 | int ret, pipein, pipeout; |
447 | struct usb_host_interface *idesc; | 435 | struct usb_host_interface *idesc; |
448 | 436 | ||
449 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 437 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
@@ -453,11 +441,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf, | |||
453 | goto out; | 441 | goto out; |
454 | } | 442 | } |
455 | 443 | ||
456 | ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL, | 444 | ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL, |
457 | &ir->dma_in); | 445 | &ir->dma_in); |
446 | ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL, | ||
447 | &ir->dma_out); | ||
458 | ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); | 448 | ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); |
449 | ir->urb_out = usb_alloc_urb(0, GFP_KERNEL); | ||
459 | 450 | ||
460 | if (!ir->buf_in || !ir->urb_in) { | 451 | if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) { |
461 | ret = -ENOMEM; | 452 | ret = -ENOMEM; |
462 | goto out; | 453 | goto out; |
463 | } | 454 | } |
@@ -472,13 +463,18 @@ static int __devinit iguanair_probe(struct usb_interface *intf, | |||
472 | ir->rc = rc; | 463 | ir->rc = rc; |
473 | ir->dev = &intf->dev; | 464 | ir->dev = &intf->dev; |
474 | ir->udev = udev; | 465 | ir->udev = udev; |
475 | ir->pipe_out = usb_sndintpipe(udev, | ||
476 | idesc->endpoint[1].desc.bEndpointAddress); | ||
477 | mutex_init(&ir->lock); | 466 | mutex_init(&ir->lock); |
467 | |||
478 | init_completion(&ir->completion); | 468 | init_completion(&ir->completion); |
469 | pipeout = usb_sndintpipe(udev, | ||
470 | idesc->endpoint[1].desc.bEndpointAddress); | ||
471 | usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET, | ||
472 | iguanair_irq_out, ir, 1); | ||
473 | ir->urb_out->transfer_dma = ir->dma_out; | ||
474 | ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
479 | 475 | ||
480 | pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress); | 476 | pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress); |
481 | usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE, | 477 | usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET, |
482 | iguanair_rx, ir, 1); | 478 | iguanair_rx, ir, 1); |
483 | ir->urb_in->transfer_dma = ir->dma_in; | 479 | ir->urb_in->transfer_dma = ir->dma_in; |
484 | ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 480 | ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
@@ -528,11 +524,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf, | |||
528 | return 0; | 524 | return 0; |
529 | out2: | 525 | out2: |
530 | usb_kill_urb(ir->urb_in); | 526 | usb_kill_urb(ir->urb_in); |
527 | usb_kill_urb(ir->urb_out); | ||
531 | out: | 528 | out: |
532 | if (ir) { | 529 | if (ir) { |
533 | usb_free_urb(ir->urb_in); | 530 | usb_free_urb(ir->urb_in); |
534 | usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in, | 531 | usb_free_urb(ir->urb_out); |
535 | ir->dma_in); | 532 | usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in); |
533 | usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet, | ||
534 | ir->dma_out); | ||
536 | } | 535 | } |
537 | rc_free_device(rc); | 536 | rc_free_device(rc); |
538 | kfree(ir); | 537 | kfree(ir); |
@@ -546,8 +545,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf) | |||
546 | rc_unregister_device(ir->rc); | 545 | rc_unregister_device(ir->rc); |
547 | usb_set_intfdata(intf, NULL); | 546 | usb_set_intfdata(intf, NULL); |
548 | usb_kill_urb(ir->urb_in); | 547 | usb_kill_urb(ir->urb_in); |
548 | usb_kill_urb(ir->urb_out); | ||
549 | usb_free_urb(ir->urb_in); | 549 | usb_free_urb(ir->urb_in); |
550 | usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in); | 550 | usb_free_urb(ir->urb_out); |
551 | usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in); | ||
552 | usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out); | ||
551 | kfree(ir); | 553 | kfree(ir); |
552 | } | 554 | } |
553 | 555 | ||
@@ -565,6 +567,7 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message) | |||
565 | } | 567 | } |
566 | 568 | ||
567 | usb_kill_urb(ir->urb_in); | 569 | usb_kill_urb(ir->urb_in); |
570 | usb_kill_urb(ir->urb_out); | ||
568 | 571 | ||
569 | mutex_unlock(&ir->lock); | 572 | mutex_unlock(&ir->lock); |
570 | 573 | ||
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 569124b03de3..870c93052fd0 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c | |||
@@ -203,13 +203,13 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
203 | /* TX settings */ | 203 | /* TX settings */ |
204 | case LIRC_SET_TRANSMITTER_MASK: | 204 | case LIRC_SET_TRANSMITTER_MASK: |
205 | if (!dev->s_tx_mask) | 205 | if (!dev->s_tx_mask) |
206 | return -EINVAL; | 206 | return -ENOSYS; |
207 | 207 | ||
208 | return dev->s_tx_mask(dev, val); | 208 | return dev->s_tx_mask(dev, val); |
209 | 209 | ||
210 | case LIRC_SET_SEND_CARRIER: | 210 | case LIRC_SET_SEND_CARRIER: |
211 | if (!dev->s_tx_carrier) | 211 | if (!dev->s_tx_carrier) |
212 | return -EINVAL; | 212 | return -ENOSYS; |
213 | 213 | ||
214 | return dev->s_tx_carrier(dev, val); | 214 | return dev->s_tx_carrier(dev, val); |
215 | 215 | ||
diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c index c64e9e30045d..2fa71d0d72d7 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c | |||
@@ -22,24 +22,24 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | 23 | ||
24 | static struct rc_map_table msi_digivox_ii[] = { | 24 | static struct rc_map_table msi_digivox_ii[] = { |
25 | { 0x0002, KEY_2 }, | 25 | { 0x0302, KEY_2 }, |
26 | { 0x0003, KEY_UP }, /* up */ | 26 | { 0x0303, KEY_UP }, /* up */ |
27 | { 0x0004, KEY_3 }, | 27 | { 0x0304, KEY_3 }, |
28 | { 0x0005, KEY_CHANNELDOWN }, | 28 | { 0x0305, KEY_CHANNELDOWN }, |
29 | { 0x0008, KEY_5 }, | 29 | { 0x0308, KEY_5 }, |
30 | { 0x0009, KEY_0 }, | 30 | { 0x0309, KEY_0 }, |
31 | { 0x000b, KEY_8 }, | 31 | { 0x030b, KEY_8 }, |
32 | { 0x000d, KEY_DOWN }, /* down */ | 32 | { 0x030d, KEY_DOWN }, /* down */ |
33 | { 0x0010, KEY_9 }, | 33 | { 0x0310, KEY_9 }, |
34 | { 0x0011, KEY_7 }, | 34 | { 0x0311, KEY_7 }, |
35 | { 0x0014, KEY_VOLUMEUP }, | 35 | { 0x0314, KEY_VOLUMEUP }, |
36 | { 0x0015, KEY_CHANNELUP }, | 36 | { 0x0315, KEY_CHANNELUP }, |
37 | { 0x0016, KEY_OK }, | 37 | { 0x0316, KEY_OK }, |
38 | { 0x0017, KEY_POWER2 }, | 38 | { 0x0317, KEY_POWER2 }, |
39 | { 0x001a, KEY_1 }, | 39 | { 0x031a, KEY_1 }, |
40 | { 0x001c, KEY_4 }, | 40 | { 0x031c, KEY_4 }, |
41 | { 0x001d, KEY_6 }, | 41 | { 0x031d, KEY_6 }, |
42 | { 0x001f, KEY_VOLUMEDOWN }, | 42 | { 0x031f, KEY_VOLUMEDOWN }, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static struct rc_map_list msi_digivox_ii_map = { | 45 | static struct rc_map_list msi_digivox_ii_map = { |
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 699eef39128b..2ea913a44ae8 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c | |||
@@ -517,6 +517,9 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier) | |||
517 | struct nvt_dev *nvt = dev->priv; | 517 | struct nvt_dev *nvt = dev->priv; |
518 | u16 val; | 518 | u16 val; |
519 | 519 | ||
520 | if (carrier == 0) | ||
521 | return -EINVAL; | ||
522 | |||
520 | nvt_cir_reg_write(nvt, 1, CIR_CP); | 523 | nvt_cir_reg_write(nvt, 1, CIR_CP); |
521 | val = 3000000 / (carrier) - 1; | 524 | val = 3000000 / (carrier) - 1; |
522 | nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); | 525 | nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); |
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 49731b1a9c57..9f5a17bb5ef5 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c | |||
@@ -890,6 +890,9 @@ static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier) | |||
890 | struct device *dev = rr3->dev; | 890 | struct device *dev = rr3->dev; |
891 | 891 | ||
892 | rr3_dbg(dev, "Setting modulation frequency to %u", carrier); | 892 | rr3_dbg(dev, "Setting modulation frequency to %u", carrier); |
893 | if (carrier == 0) | ||
894 | return -EINVAL; | ||
895 | |||
893 | rr3->carrier = carrier; | 896 | rr3->carrier = carrier; |
894 | 897 | ||
895 | return carrier; | 898 | return carrier; |
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 30ae1f24abc3..7c9b5f33113b 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c | |||
@@ -184,7 +184,7 @@ enum wbcir_txstate { | |||
184 | }; | 184 | }; |
185 | 185 | ||
186 | /* Misc */ | 186 | /* Misc */ |
187 | #define WBCIR_NAME "Winbond CIR" | 187 | #define WBCIR_NAME "winbond-cir" |
188 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ | 188 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ |
189 | #define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ | 189 | #define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ |
190 | #define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ | 190 | #define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ |
diff --git a/drivers/media/tuners/mt2063.c b/drivers/media/tuners/mt2063.c index 0ed9091ff48e..2e1a02e360ff 100644 --- a/drivers/media/tuners/mt2063.c +++ b/drivers/media/tuners/mt2063.c | |||
@@ -245,7 +245,7 @@ struct mt2063_state { | |||
245 | /* | 245 | /* |
246 | * mt2063_write - Write data into the I2C bus | 246 | * mt2063_write - Write data into the I2C bus |
247 | */ | 247 | */ |
248 | static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len) | 248 | static int mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len) |
249 | { | 249 | { |
250 | struct dvb_frontend *fe = state->frontend; | 250 | struct dvb_frontend *fe = state->frontend; |
251 | int ret; | 251 | int ret; |
@@ -277,9 +277,9 @@ static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len) | |||
277 | /* | 277 | /* |
278 | * mt2063_write - Write register data into the I2C bus, caching the value | 278 | * mt2063_write - Write register data into the I2C bus, caching the value |
279 | */ | 279 | */ |
280 | static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val) | 280 | static int mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val) |
281 | { | 281 | { |
282 | u32 status; | 282 | int status; |
283 | 283 | ||
284 | dprintk(2, "\n"); | 284 | dprintk(2, "\n"); |
285 | 285 | ||
@@ -298,10 +298,10 @@ static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val) | |||
298 | /* | 298 | /* |
299 | * mt2063_read - Read data from the I2C bus | 299 | * mt2063_read - Read data from the I2C bus |
300 | */ | 300 | */ |
301 | static u32 mt2063_read(struct mt2063_state *state, | 301 | static int mt2063_read(struct mt2063_state *state, |
302 | u8 subAddress, u8 *pData, u32 cnt) | 302 | u8 subAddress, u8 *pData, u32 cnt) |
303 | { | 303 | { |
304 | u32 status = 0; /* Status to be returned */ | 304 | int status = 0; /* Status to be returned */ |
305 | struct dvb_frontend *fe = state->frontend; | 305 | struct dvb_frontend *fe = state->frontend; |
306 | u32 i = 0; | 306 | u32 i = 0; |
307 | 307 | ||
@@ -816,7 +816,7 @@ static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info, | |||
816 | */ | 816 | */ |
817 | static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info) | 817 | static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info) |
818 | { | 818 | { |
819 | u32 status = 0; | 819 | int status = 0; |
820 | u32 fm, fp; /* restricted range on LO's */ | 820 | u32 fm, fp; /* restricted range on LO's */ |
821 | pAS_Info->bSpurAvoided = 0; | 821 | pAS_Info->bSpurAvoided = 0; |
822 | pAS_Info->nSpursFound = 0; | 822 | pAS_Info->nSpursFound = 0; |
@@ -935,14 +935,14 @@ static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info) | |||
935 | * | 935 | * |
936 | * This function returns 0, if no lock, 1 if locked and a value < 1 if error | 936 | * This function returns 0, if no lock, 1 if locked and a value < 1 if error |
937 | */ | 937 | */ |
938 | static unsigned int mt2063_lockStatus(struct mt2063_state *state) | 938 | static int mt2063_lockStatus(struct mt2063_state *state) |
939 | { | 939 | { |
940 | const u32 nMaxWait = 100; /* wait a maximum of 100 msec */ | 940 | const u32 nMaxWait = 100; /* wait a maximum of 100 msec */ |
941 | const u32 nPollRate = 2; /* poll status bits every 2 ms */ | 941 | const u32 nPollRate = 2; /* poll status bits every 2 ms */ |
942 | const u32 nMaxLoops = nMaxWait / nPollRate; | 942 | const u32 nMaxLoops = nMaxWait / nPollRate; |
943 | const u8 LO1LK = 0x80; | 943 | const u8 LO1LK = 0x80; |
944 | u8 LO2LK = 0x08; | 944 | u8 LO2LK = 0x08; |
945 | u32 status; | 945 | int status; |
946 | u32 nDelays = 0; | 946 | u32 nDelays = 0; |
947 | 947 | ||
948 | dprintk(2, "\n"); | 948 | dprintk(2, "\n"); |
@@ -1069,7 +1069,7 @@ static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state, | |||
1069 | static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state, | 1069 | static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state, |
1070 | enum MT2063_DNC_Output_Enable nValue) | 1070 | enum MT2063_DNC_Output_Enable nValue) |
1071 | { | 1071 | { |
1072 | u32 status = 0; /* Status to be returned */ | 1072 | int status = 0; /* Status to be returned */ |
1073 | u8 val = 0; | 1073 | u8 val = 0; |
1074 | 1074 | ||
1075 | dprintk(2, "\n"); | 1075 | dprintk(2, "\n"); |
@@ -1203,7 +1203,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state, | |||
1203 | static u32 MT2063_SetReceiverMode(struct mt2063_state *state, | 1203 | static u32 MT2063_SetReceiverMode(struct mt2063_state *state, |
1204 | enum mt2063_delivery_sys Mode) | 1204 | enum mt2063_delivery_sys Mode) |
1205 | { | 1205 | { |
1206 | u32 status = 0; /* Status to be returned */ | 1206 | int status = 0; /* Status to be returned */ |
1207 | u8 val; | 1207 | u8 val; |
1208 | u32 longval; | 1208 | u32 longval; |
1209 | 1209 | ||
@@ -1345,7 +1345,7 @@ static u32 MT2063_SetReceiverMode(struct mt2063_state *state, | |||
1345 | static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, | 1345 | static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, |
1346 | enum MT2063_Mask_Bits Bits) | 1346 | enum MT2063_Mask_Bits Bits) |
1347 | { | 1347 | { |
1348 | u32 status = 0; | 1348 | int status = 0; |
1349 | 1349 | ||
1350 | dprintk(2, "\n"); | 1350 | dprintk(2, "\n"); |
1351 | Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */ | 1351 | Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */ |
@@ -1374,7 +1374,7 @@ static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, | |||
1374 | */ | 1374 | */ |
1375 | static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown) | 1375 | static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown) |
1376 | { | 1376 | { |
1377 | u32 status; | 1377 | int status; |
1378 | 1378 | ||
1379 | dprintk(2, "\n"); | 1379 | dprintk(2, "\n"); |
1380 | if (Shutdown == 1) | 1380 | if (Shutdown == 1) |
@@ -1540,7 +1540,7 @@ static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in) | |||
1540 | static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in) | 1540 | static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in) |
1541 | { /* RF input center frequency */ | 1541 | { /* RF input center frequency */ |
1542 | 1542 | ||
1543 | u32 status = 0; | 1543 | int status = 0; |
1544 | u32 LO1; /* 1st LO register value */ | 1544 | u32 LO1; /* 1st LO register value */ |
1545 | u32 Num1; /* Numerator for LO1 reg. value */ | 1545 | u32 Num1; /* Numerator for LO1 reg. value */ |
1546 | u32 f_IF1; /* 1st IF requested */ | 1546 | u32 f_IF1; /* 1st IF requested */ |
@@ -1803,7 +1803,7 @@ static const u8 MT2063B3_defaults[] = { | |||
1803 | 1803 | ||
1804 | static int mt2063_init(struct dvb_frontend *fe) | 1804 | static int mt2063_init(struct dvb_frontend *fe) |
1805 | { | 1805 | { |
1806 | u32 status; | 1806 | int status; |
1807 | struct mt2063_state *state = fe->tuner_priv; | 1807 | struct mt2063_state *state = fe->tuner_priv; |
1808 | u8 all_resets = 0xF0; /* reset/load bits */ | 1808 | u8 all_resets = 0xF0; /* reset/load bits */ |
1809 | const u8 *def = NULL; | 1809 | const u8 *def = NULL; |
@@ -2249,8 +2249,8 @@ struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, | |||
2249 | dprintk(2, "\n"); | 2249 | dprintk(2, "\n"); |
2250 | 2250 | ||
2251 | state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL); | 2251 | state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL); |
2252 | if (state == NULL) | 2252 | if (!state) |
2253 | goto error; | 2253 | return NULL; |
2254 | 2254 | ||
2255 | state->config = config; | 2255 | state->config = config; |
2256 | state->i2c = i2c; | 2256 | state->i2c = i2c; |
@@ -2261,18 +2261,15 @@ struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, | |||
2261 | 2261 | ||
2262 | printk(KERN_INFO "%s: Attaching MT2063\n", __func__); | 2262 | printk(KERN_INFO "%s: Attaching MT2063\n", __func__); |
2263 | return fe; | 2263 | return fe; |
2264 | |||
2265 | error: | ||
2266 | kfree(state); | ||
2267 | return NULL; | ||
2268 | } | 2264 | } |
2269 | EXPORT_SYMBOL_GPL(mt2063_attach); | 2265 | EXPORT_SYMBOL_GPL(mt2063_attach); |
2270 | 2266 | ||
2267 | #if 0 | ||
2271 | /* | 2268 | /* |
2272 | * Ancillary routines visible outside mt2063 | 2269 | * Ancillary routines visible outside mt2063 |
2273 | * FIXME: Remove them in favor of using standard tuner callbacks | 2270 | * FIXME: Remove them in favor of using standard tuner callbacks |
2274 | */ | 2271 | */ |
2275 | unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe) | 2272 | static int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe) |
2276 | { | 2273 | { |
2277 | struct mt2063_state *state = fe->tuner_priv; | 2274 | struct mt2063_state *state = fe->tuner_priv; |
2278 | int err = 0; | 2275 | int err = 0; |
@@ -2285,9 +2282,8 @@ unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe) | |||
2285 | 2282 | ||
2286 | return err; | 2283 | return err; |
2287 | } | 2284 | } |
2288 | EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown); | ||
2289 | 2285 | ||
2290 | unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe) | 2286 | static int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe) |
2291 | { | 2287 | { |
2292 | struct mt2063_state *state = fe->tuner_priv; | 2288 | struct mt2063_state *state = fe->tuner_priv; |
2293 | int err = 0; | 2289 | int err = 0; |
@@ -2300,7 +2296,7 @@ unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe) | |||
2300 | 2296 | ||
2301 | return err; | 2297 | return err; |
2302 | } | 2298 | } |
2303 | EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits); | 2299 | #endif |
2304 | 2300 | ||
2305 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | 2301 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); |
2306 | MODULE_DESCRIPTION("MT2063 Silicon tuner"); | 2302 | MODULE_DESCRIPTION("MT2063 Silicon tuner"); |
diff --git a/drivers/media/tuners/mt2063.h b/drivers/media/tuners/mt2063.h index 3f5cfd93713f..ab24170c1571 100644 --- a/drivers/media/tuners/mt2063.h +++ b/drivers/media/tuners/mt2063.h | |||
@@ -23,10 +23,6 @@ static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, | |||
23 | return NULL; | 23 | return NULL; |
24 | } | 24 | } |
25 | 25 | ||
26 | /* FIXME: Should use the standard DVB attachment interfaces */ | ||
27 | unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe); | ||
28 | unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe); | ||
29 | |||
30 | #endif /* CONFIG_DVB_MT2063 */ | 26 | #endif /* CONFIG_DVB_MT2063 */ |
31 | 27 | ||
32 | #endif /* __MT2063_H__ */ | 28 | #endif /* __MT2063_H__ */ |
diff --git a/drivers/media/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c index 221171eeb0c3..18c77afe2e4f 100644 --- a/drivers/media/tuners/tda18271-common.c +++ b/drivers/media/tuners/tda18271-common.c | |||
@@ -187,7 +187,8 @@ int tda18271_read_extended(struct dvb_frontend *fe) | |||
187 | return (ret == 2 ? 0 : ret); | 187 | return (ret == 2 ? 0 : ret); |
188 | } | 188 | } |
189 | 189 | ||
190 | int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | 190 | static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len, |
191 | bool lock_i2c) | ||
191 | { | 192 | { |
192 | struct tda18271_priv *priv = fe->tuner_priv; | 193 | struct tda18271_priv *priv = fe->tuner_priv; |
193 | unsigned char *regs = priv->tda18271_regs; | 194 | unsigned char *regs = priv->tda18271_regs; |
@@ -198,7 +199,6 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
198 | 199 | ||
199 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); | 200 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); |
200 | 201 | ||
201 | |||
202 | switch (priv->small_i2c) { | 202 | switch (priv->small_i2c) { |
203 | case TDA18271_03_BYTE_CHUNK_INIT: | 203 | case TDA18271_03_BYTE_CHUNK_INIT: |
204 | max = 3; | 204 | max = 3; |
@@ -214,7 +214,19 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
214 | max = 39; | 214 | max = 39; |
215 | } | 215 | } |
216 | 216 | ||
217 | tda18271_i2c_gate_ctrl(fe, 1); | 217 | |
218 | /* | ||
219 | * If lock_i2c is true, it will take the I2C bus for tda18271 private | ||
220 | * usage during the entire write ops, as otherwise, bad things could | ||
221 | * happen. | ||
222 | * During device init, several write operations will happen. So, | ||
223 | * tda18271_init_regs controls the I2C lock directly, | ||
224 | * disabling lock_i2c here. | ||
225 | */ | ||
226 | if (lock_i2c) { | ||
227 | tda18271_i2c_gate_ctrl(fe, 1); | ||
228 | i2c_lock_adapter(priv->i2c_props.adap); | ||
229 | } | ||
218 | while (len) { | 230 | while (len) { |
219 | if (max > len) | 231 | if (max > len) |
220 | max = len; | 232 | max = len; |
@@ -226,14 +238,17 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
226 | msg.len = max + 1; | 238 | msg.len = max + 1; |
227 | 239 | ||
228 | /* write registers */ | 240 | /* write registers */ |
229 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | 241 | ret = __i2c_transfer(priv->i2c_props.adap, &msg, 1); |
230 | if (ret != 1) | 242 | if (ret != 1) |
231 | break; | 243 | break; |
232 | 244 | ||
233 | idx += max; | 245 | idx += max; |
234 | len -= max; | 246 | len -= max; |
235 | } | 247 | } |
236 | tda18271_i2c_gate_ctrl(fe, 0); | 248 | if (lock_i2c) { |
249 | i2c_unlock_adapter(priv->i2c_props.adap); | ||
250 | tda18271_i2c_gate_ctrl(fe, 0); | ||
251 | } | ||
237 | 252 | ||
238 | if (ret != 1) | 253 | if (ret != 1) |
239 | tda_err("ERROR: idx = 0x%x, len = %d, " | 254 | tda_err("ERROR: idx = 0x%x, len = %d, " |
@@ -242,10 +257,16 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
242 | return (ret == 1 ? 0 : ret); | 257 | return (ret == 1 ? 0 : ret); |
243 | } | 258 | } |
244 | 259 | ||
260 | int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | ||
261 | { | ||
262 | return __tda18271_write_regs(fe, idx, len, true); | ||
263 | } | ||
264 | |||
245 | /*---------------------------------------------------------------------*/ | 265 | /*---------------------------------------------------------------------*/ |
246 | 266 | ||
247 | int tda18271_charge_pump_source(struct dvb_frontend *fe, | 267 | static int __tda18271_charge_pump_source(struct dvb_frontend *fe, |
248 | enum tda18271_pll pll, int force) | 268 | enum tda18271_pll pll, int force, |
269 | bool lock_i2c) | ||
249 | { | 270 | { |
250 | struct tda18271_priv *priv = fe->tuner_priv; | 271 | struct tda18271_priv *priv = fe->tuner_priv; |
251 | unsigned char *regs = priv->tda18271_regs; | 272 | unsigned char *regs = priv->tda18271_regs; |
@@ -255,9 +276,16 @@ int tda18271_charge_pump_source(struct dvb_frontend *fe, | |||
255 | regs[r_cp] &= ~0x20; | 276 | regs[r_cp] &= ~0x20; |
256 | regs[r_cp] |= ((force & 1) << 5); | 277 | regs[r_cp] |= ((force & 1) << 5); |
257 | 278 | ||
258 | return tda18271_write_regs(fe, r_cp, 1); | 279 | return __tda18271_write_regs(fe, r_cp, 1, lock_i2c); |
280 | } | ||
281 | |||
282 | int tda18271_charge_pump_source(struct dvb_frontend *fe, | ||
283 | enum tda18271_pll pll, int force) | ||
284 | { | ||
285 | return __tda18271_charge_pump_source(fe, pll, force, true); | ||
259 | } | 286 | } |
260 | 287 | ||
288 | |||
261 | int tda18271_init_regs(struct dvb_frontend *fe) | 289 | int tda18271_init_regs(struct dvb_frontend *fe) |
262 | { | 290 | { |
263 | struct tda18271_priv *priv = fe->tuner_priv; | 291 | struct tda18271_priv *priv = fe->tuner_priv; |
@@ -267,6 +295,13 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
267 | i2c_adapter_id(priv->i2c_props.adap), | 295 | i2c_adapter_id(priv->i2c_props.adap), |
268 | priv->i2c_props.addr); | 296 | priv->i2c_props.addr); |
269 | 297 | ||
298 | /* | ||
299 | * Don't let any other I2C transfer to happen at adapter during init, | ||
300 | * as those could cause bad things | ||
301 | */ | ||
302 | tda18271_i2c_gate_ctrl(fe, 1); | ||
303 | i2c_lock_adapter(priv->i2c_props.adap); | ||
304 | |||
270 | /* initialize registers */ | 305 | /* initialize registers */ |
271 | switch (priv->id) { | 306 | switch (priv->id) { |
272 | case TDA18271HDC1: | 307 | case TDA18271HDC1: |
@@ -352,28 +387,28 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
352 | regs[R_EB22] = 0x48; | 387 | regs[R_EB22] = 0x48; |
353 | regs[R_EB23] = 0xb0; | 388 | regs[R_EB23] = 0xb0; |
354 | 389 | ||
355 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); | 390 | __tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS, false); |
356 | 391 | ||
357 | /* setup agc1 gain */ | 392 | /* setup agc1 gain */ |
358 | regs[R_EB17] = 0x00; | 393 | regs[R_EB17] = 0x00; |
359 | tda18271_write_regs(fe, R_EB17, 1); | 394 | __tda18271_write_regs(fe, R_EB17, 1, false); |
360 | regs[R_EB17] = 0x03; | 395 | regs[R_EB17] = 0x03; |
361 | tda18271_write_regs(fe, R_EB17, 1); | 396 | __tda18271_write_regs(fe, R_EB17, 1, false); |
362 | regs[R_EB17] = 0x43; | 397 | regs[R_EB17] = 0x43; |
363 | tda18271_write_regs(fe, R_EB17, 1); | 398 | __tda18271_write_regs(fe, R_EB17, 1, false); |
364 | regs[R_EB17] = 0x4c; | 399 | regs[R_EB17] = 0x4c; |
365 | tda18271_write_regs(fe, R_EB17, 1); | 400 | __tda18271_write_regs(fe, R_EB17, 1, false); |
366 | 401 | ||
367 | /* setup agc2 gain */ | 402 | /* setup agc2 gain */ |
368 | if ((priv->id) == TDA18271HDC1) { | 403 | if ((priv->id) == TDA18271HDC1) { |
369 | regs[R_EB20] = 0xa0; | 404 | regs[R_EB20] = 0xa0; |
370 | tda18271_write_regs(fe, R_EB20, 1); | 405 | __tda18271_write_regs(fe, R_EB20, 1, false); |
371 | regs[R_EB20] = 0xa7; | 406 | regs[R_EB20] = 0xa7; |
372 | tda18271_write_regs(fe, R_EB20, 1); | 407 | __tda18271_write_regs(fe, R_EB20, 1, false); |
373 | regs[R_EB20] = 0xe7; | 408 | regs[R_EB20] = 0xe7; |
374 | tda18271_write_regs(fe, R_EB20, 1); | 409 | __tda18271_write_regs(fe, R_EB20, 1, false); |
375 | regs[R_EB20] = 0xec; | 410 | regs[R_EB20] = 0xec; |
376 | tda18271_write_regs(fe, R_EB20, 1); | 411 | __tda18271_write_regs(fe, R_EB20, 1, false); |
377 | } | 412 | } |
378 | 413 | ||
379 | /* image rejection calibration */ | 414 | /* image rejection calibration */ |
@@ -391,21 +426,21 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
391 | regs[R_MD2] = 0x08; | 426 | regs[R_MD2] = 0x08; |
392 | regs[R_MD3] = 0x00; | 427 | regs[R_MD3] = 0x00; |
393 | 428 | ||
394 | tda18271_write_regs(fe, R_EP3, 11); | 429 | __tda18271_write_regs(fe, R_EP3, 11, false); |
395 | 430 | ||
396 | if ((priv->id) == TDA18271HDC2) { | 431 | if ((priv->id) == TDA18271HDC2) { |
397 | /* main pll cp source on */ | 432 | /* main pll cp source on */ |
398 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); | 433 | __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1, false); |
399 | msleep(1); | 434 | msleep(1); |
400 | 435 | ||
401 | /* main pll cp source off */ | 436 | /* main pll cp source off */ |
402 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); | 437 | __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0, false); |
403 | } | 438 | } |
404 | 439 | ||
405 | msleep(5); /* pll locking */ | 440 | msleep(5); /* pll locking */ |
406 | 441 | ||
407 | /* launch detector */ | 442 | /* launch detector */ |
408 | tda18271_write_regs(fe, R_EP1, 1); | 443 | __tda18271_write_regs(fe, R_EP1, 1, false); |
409 | msleep(5); /* wanted low measurement */ | 444 | msleep(5); /* wanted low measurement */ |
410 | 445 | ||
411 | regs[R_EP5] = 0x85; | 446 | regs[R_EP5] = 0x85; |
@@ -413,11 +448,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
413 | regs[R_CD1] = 0x66; | 448 | regs[R_CD1] = 0x66; |
414 | regs[R_CD2] = 0x70; | 449 | regs[R_CD2] = 0x70; |
415 | 450 | ||
416 | tda18271_write_regs(fe, R_EP3, 7); | 451 | __tda18271_write_regs(fe, R_EP3, 7, false); |
417 | msleep(5); /* pll locking */ | 452 | msleep(5); /* pll locking */ |
418 | 453 | ||
419 | /* launch optimization algorithm */ | 454 | /* launch optimization algorithm */ |
420 | tda18271_write_regs(fe, R_EP2, 1); | 455 | __tda18271_write_regs(fe, R_EP2, 1, false); |
421 | msleep(30); /* image low optimization completion */ | 456 | msleep(30); /* image low optimization completion */ |
422 | 457 | ||
423 | /* mid-band */ | 458 | /* mid-band */ |
@@ -428,11 +463,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
428 | regs[R_MD1] = 0x73; | 463 | regs[R_MD1] = 0x73; |
429 | regs[R_MD2] = 0x1a; | 464 | regs[R_MD2] = 0x1a; |
430 | 465 | ||
431 | tda18271_write_regs(fe, R_EP3, 11); | 466 | __tda18271_write_regs(fe, R_EP3, 11, false); |
432 | msleep(5); /* pll locking */ | 467 | msleep(5); /* pll locking */ |
433 | 468 | ||
434 | /* launch detector */ | 469 | /* launch detector */ |
435 | tda18271_write_regs(fe, R_EP1, 1); | 470 | __tda18271_write_regs(fe, R_EP1, 1, false); |
436 | msleep(5); /* wanted mid measurement */ | 471 | msleep(5); /* wanted mid measurement */ |
437 | 472 | ||
438 | regs[R_EP5] = 0x86; | 473 | regs[R_EP5] = 0x86; |
@@ -440,11 +475,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
440 | regs[R_CD1] = 0x66; | 475 | regs[R_CD1] = 0x66; |
441 | regs[R_CD2] = 0xa0; | 476 | regs[R_CD2] = 0xa0; |
442 | 477 | ||
443 | tda18271_write_regs(fe, R_EP3, 7); | 478 | __tda18271_write_regs(fe, R_EP3, 7, false); |
444 | msleep(5); /* pll locking */ | 479 | msleep(5); /* pll locking */ |
445 | 480 | ||
446 | /* launch optimization algorithm */ | 481 | /* launch optimization algorithm */ |
447 | tda18271_write_regs(fe, R_EP2, 1); | 482 | __tda18271_write_regs(fe, R_EP2, 1, false); |
448 | msleep(30); /* image mid optimization completion */ | 483 | msleep(30); /* image mid optimization completion */ |
449 | 484 | ||
450 | /* high-band */ | 485 | /* high-band */ |
@@ -456,30 +491,33 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
456 | regs[R_MD1] = 0x71; | 491 | regs[R_MD1] = 0x71; |
457 | regs[R_MD2] = 0xcd; | 492 | regs[R_MD2] = 0xcd; |
458 | 493 | ||
459 | tda18271_write_regs(fe, R_EP3, 11); | 494 | __tda18271_write_regs(fe, R_EP3, 11, false); |
460 | msleep(5); /* pll locking */ | 495 | msleep(5); /* pll locking */ |
461 | 496 | ||
462 | /* launch detector */ | 497 | /* launch detector */ |
463 | tda18271_write_regs(fe, R_EP1, 1); | 498 | __tda18271_write_regs(fe, R_EP1, 1, false); |
464 | msleep(5); /* wanted high measurement */ | 499 | msleep(5); /* wanted high measurement */ |
465 | 500 | ||
466 | regs[R_EP5] = 0x87; | 501 | regs[R_EP5] = 0x87; |
467 | regs[R_CD1] = 0x65; | 502 | regs[R_CD1] = 0x65; |
468 | regs[R_CD2] = 0x50; | 503 | regs[R_CD2] = 0x50; |
469 | 504 | ||
470 | tda18271_write_regs(fe, R_EP3, 7); | 505 | __tda18271_write_regs(fe, R_EP3, 7, false); |
471 | msleep(5); /* pll locking */ | 506 | msleep(5); /* pll locking */ |
472 | 507 | ||
473 | /* launch optimization algorithm */ | 508 | /* launch optimization algorithm */ |
474 | tda18271_write_regs(fe, R_EP2, 1); | 509 | __tda18271_write_regs(fe, R_EP2, 1, false); |
475 | msleep(30); /* image high optimization completion */ | 510 | msleep(30); /* image high optimization completion */ |
476 | 511 | ||
477 | /* return to normal mode */ | 512 | /* return to normal mode */ |
478 | regs[R_EP4] = 0x64; | 513 | regs[R_EP4] = 0x64; |
479 | tda18271_write_regs(fe, R_EP4, 1); | 514 | __tda18271_write_regs(fe, R_EP4, 1, false); |
480 | 515 | ||
481 | /* synchronize */ | 516 | /* synchronize */ |
482 | tda18271_write_regs(fe, R_EP1, 1); | 517 | __tda18271_write_regs(fe, R_EP1, 1, false); |
518 | |||
519 | i2c_unlock_adapter(priv->i2c_props.adap); | ||
520 | tda18271_i2c_gate_ctrl(fe, 0); | ||
483 | 521 | ||
484 | return 0; | 522 | return 0; |
485 | } | 523 | } |
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index 824f1911ee21..3d7526e28d42 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c | |||
@@ -500,7 +500,7 @@ static int af9015_read_config(struct dvb_usb_device *d) | |||
500 | case 3: | 500 | case 3: |
501 | state->af9013_config[i].clock = 25000000; | 501 | state->af9013_config[i].clock = 25000000; |
502 | break; | 502 | break; |
503 | }; | 503 | } |
504 | dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n", | 504 | dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n", |
505 | __func__, i, val, | 505 | __func__, i, val, |
506 | state->af9013_config[i].clock); | 506 | state->af9013_config[i].clock); |
@@ -568,7 +568,7 @@ static int af9015_read_config(struct dvb_usb_device *d) | |||
568 | "supported, please report!\n", | 568 | "supported, please report!\n", |
569 | KBUILD_MODNAME, val); | 569 | KBUILD_MODNAME, val); |
570 | return -ENODEV; | 570 | return -ENODEV; |
571 | }; | 571 | } |
572 | 572 | ||
573 | state->af9013_config[i].tuner = val; | 573 | state->af9013_config[i].tuner = val; |
574 | dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n", | 574 | dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n", |
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index aabd3fc03ea7..ea27eaff4e34 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c | |||
@@ -520,7 +520,7 @@ static int af9035_read_config(struct dvb_usb_device *d) | |||
520 | dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \ | 520 | dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \ |
521 | "supported, please report!", | 521 | "supported, please report!", |
522 | KBUILD_MODNAME, tmp); | 522 | KBUILD_MODNAME, tmp); |
523 | }; | 523 | } |
524 | 524 | ||
525 | /* tuner IF frequency */ | 525 | /* tuner IF frequency */ |
526 | ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); | 526 | ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); |
diff --git a/drivers/media/usb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c index 8d7fef84afd8..83684ed023cd 100644 --- a/drivers/media/usb/dvb-usb/a800.c +++ b/drivers/media/usb/dvb-usb/a800.c | |||
@@ -93,7 +93,7 @@ static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
93 | /* call the universal NEC remote processor, to find out the key's state and event */ | 93 | /* call the universal NEC remote processor, to find out the key's state and event */ |
94 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | 94 | dvb_usb_nec_rc_key_to_event(d,key,event,state); |
95 | if (key[0] != 0) | 95 | if (key[0] != 0) |
96 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | 96 | deb_rc("key: %*ph\n", 5, key); |
97 | ret = 0; | 97 | ret = 0; |
98 | out: | 98 | out: |
99 | kfree(key); | 99 | kfree(key); |
diff --git a/drivers/media/usb/dvb-usb/cinergyT2-core.c b/drivers/media/usb/dvb-usb/cinergyT2-core.c index 0a98548ecd17..9fd1527494eb 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-core.c | |||
@@ -172,8 +172,7 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
172 | if (*event != d->last_event) | 172 | if (*event != d->last_event) |
173 | st->rc_counter = 0; | 173 | st->rc_counter = 0; |
174 | 174 | ||
175 | deb_rc("key: %x %x %x %x %x\n", | 175 | deb_rc("key: %*ph\n", 5, key); |
176 | key[0], key[1], key[2], key[3], key[4]); | ||
177 | } | 176 | } |
178 | return 0; | 177 | return 0; |
179 | } | 178 | } |
diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index a76bbb29ca36..af0d4321845b 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c | |||
@@ -473,7 +473,7 @@ int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
473 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | 473 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); |
474 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | 474 | dvb_usb_nec_rc_key_to_event(d,key,event,state); |
475 | if (key[0] != 0) | 475 | if (key[0] != 0) |
476 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | 476 | deb_info("key: %*ph\n", 5, key); |
477 | return 0; | 477 | return 0; |
478 | } | 478 | } |
479 | EXPORT_SYMBOL(dibusb_rc_query); | 479 | EXPORT_SYMBOL(dibusb_rc_query); |
diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index ff34419a4c88..772bde3c5020 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c | |||
@@ -253,7 +253,7 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | if (key[0] != 0) | 255 | if (key[0] != 0) |
256 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | 256 | deb_rc("key: %*ph\n", 5, key); |
257 | return 0; | 257 | return 0; |
258 | } | 258 | } |
259 | 259 | ||
diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index 66f205c112b2..c357fb3b0a88 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c | |||
@@ -84,7 +84,7 @@ static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
84 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | 84 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); |
85 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | 85 | dvb_usb_nec_rc_key_to_event(d,key,event,state); |
86 | if (key[0] != 0) | 86 | if (key[0] != 0) |
87 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | 87 | deb_info("key: %*ph\n", 5, key); |
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index 288af29a8bb7..661bb75be955 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c | |||
@@ -358,7 +358,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar | |||
358 | 358 | ||
359 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) | 359 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) |
360 | goto done; | 360 | goto done; |
361 | deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]); | 361 | deb("%*ph\n", 4, read); |
362 | 362 | ||
363 | if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) | 363 | if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) |
364 | goto done; | 364 | goto done; |
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index acefaa89cc53..7a8c8c18590f 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c | |||
@@ -677,6 +677,7 @@ static struct usb_device_id technisat_usb2_id_table[] = { | |||
677 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) }, | 677 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) }, |
678 | { 0 } /* Terminating entry */ | 678 | { 0 } /* Terminating entry */ |
679 | }; | 679 | }; |
680 | MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table); | ||
680 | 681 | ||
681 | /* device description */ | 682 | /* device description */ |
682 | static struct dvb_usb_device_properties technisat_usb2_devices = { | 683 | static struct dvb_usb_device_properties technisat_usb2_devices = { |
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index f7297ae76b48..16a84f9f46d8 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c | |||
@@ -2203,7 +2203,7 @@ EXPORT_SYMBOL_GPL(em28xx_tuner_callback); | |||
2203 | 2203 | ||
2204 | static inline void em28xx_set_model(struct em28xx *dev) | 2204 | static inline void em28xx_set_model(struct em28xx *dev) |
2205 | { | 2205 | { |
2206 | memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); | 2206 | dev->board = em28xx_boards[dev->model]; |
2207 | 2207 | ||
2208 | /* Those are the default values for the majority of boards | 2208 | /* Those are the default values for the majority of boards |
2209 | Use those values if not specified otherwise at boards entry | 2209 | Use those values if not specified otherwise at boards entry |
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 913e5227897a..13ae821949e9 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c | |||
@@ -574,18 +574,19 @@ static void pctv_520e_init(struct em28xx *dev) | |||
574 | i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); | 574 | i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); |
575 | }; | 575 | }; |
576 | 576 | ||
577 | static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val) | 577 | static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) |
578 | { | 578 | { |
579 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
579 | struct em28xx *dev = fe->dvb->priv; | 580 | struct em28xx *dev = fe->dvb->priv; |
580 | #ifdef CONFIG_GPIOLIB | 581 | #ifdef CONFIG_GPIOLIB |
581 | struct em28xx_dvb *dvb = dev->dvb; | 582 | struct em28xx_dvb *dvb = dev->dvb; |
582 | int ret; | 583 | int ret; |
583 | unsigned long flags; | 584 | unsigned long flags; |
584 | 585 | ||
585 | if (val) | 586 | if (c->lna == 1) |
586 | flags = GPIOF_OUT_INIT_LOW; | 587 | flags = GPIOF_OUT_INIT_HIGH; /* enable LNA */ |
587 | else | 588 | else |
588 | flags = GPIOF_OUT_INIT_HIGH; | 589 | flags = GPIOF_OUT_INIT_LOW; /* disable LNA */ |
589 | 590 | ||
590 | ret = gpio_request_one(dvb->lna_gpio, flags, NULL); | 591 | ret = gpio_request_one(dvb->lna_gpio, flags, NULL); |
591 | if (ret) | 592 | if (ret) |
@@ -595,8 +596,8 @@ static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val) | |||
595 | 596 | ||
596 | return ret; | 597 | return ret; |
597 | #else | 598 | #else |
598 | dev_warn(&dev->udev->dev, "%s: LNA control is disabled\n", | 599 | dev_warn(&dev->udev->dev, "%s: LNA control is disabled (lna=%u)\n", |
599 | KBUILD_MODNAME); | 600 | KBUILD_MODNAME, c->lna); |
600 | return 0; | 601 | return 0; |
601 | #endif | 602 | #endif |
602 | } | 603 | } |
diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index b62740846061..34a26e0cfe77 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c | |||
@@ -100,12 +100,21 @@ int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value) | |||
100 | 100 | ||
101 | void stk1160_select_input(struct stk1160 *dev) | 101 | void stk1160_select_input(struct stk1160 *dev) |
102 | { | 102 | { |
103 | int route; | ||
103 | static const u8 gctrl[] = { | 104 | static const u8 gctrl[] = { |
104 | 0x98, 0x90, 0x88, 0x80 | 105 | 0x98, 0x90, 0x88, 0x80, 0x98 |
105 | }; | 106 | }; |
106 | 107 | ||
107 | if (dev->ctl_input < ARRAY_SIZE(gctrl)) | 108 | if (dev->ctl_input == STK1160_SVIDEO_INPUT) |
109 | route = SAA7115_SVIDEO3; | ||
110 | else | ||
111 | route = SAA7115_COMPOSITE0; | ||
112 | |||
113 | if (dev->ctl_input < ARRAY_SIZE(gctrl)) { | ||
114 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, | ||
115 | route, 0, 0); | ||
108 | stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]); | 116 | stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]); |
117 | } | ||
109 | } | 118 | } |
110 | 119 | ||
111 | /* TODO: We should break this into pieces */ | 120 | /* TODO: We should break this into pieces */ |
@@ -351,8 +360,6 @@ static int stk1160_probe(struct usb_interface *interface, | |||
351 | 360 | ||
352 | /* i2c reset saa711x */ | 361 | /* i2c reset saa711x */ |
353 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); | 362 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); |
354 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, | ||
355 | 0, 0, 0); | ||
356 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); | 363 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); |
357 | 364 | ||
358 | /* reset stk1160 to default values */ | 365 | /* reset stk1160 to default values */ |
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index fe6e857969ca..6694f9e2ca57 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c | |||
@@ -419,7 +419,12 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
419 | if (i->index > STK1160_MAX_INPUT) | 419 | if (i->index > STK1160_MAX_INPUT) |
420 | return -EINVAL; | 420 | return -EINVAL; |
421 | 421 | ||
422 | sprintf(i->name, "Composite%d", i->index); | 422 | /* S-Video special handling */ |
423 | if (i->index == STK1160_SVIDEO_INPUT) | ||
424 | sprintf(i->name, "S-Video"); | ||
425 | else | ||
426 | sprintf(i->name, "Composite%d", i->index); | ||
427 | |||
423 | i->type = V4L2_INPUT_TYPE_CAMERA; | 428 | i->type = V4L2_INPUT_TYPE_CAMERA; |
424 | i->std = dev->vdev.tvnorms; | 429 | i->std = dev->vdev.tvnorms; |
425 | return 0; | 430 | return 0; |
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h index 3feba0033f98..68c8707d36ab 100644 --- a/drivers/media/usb/stk1160/stk1160.h +++ b/drivers/media/usb/stk1160/stk1160.h | |||
@@ -46,7 +46,8 @@ | |||
46 | 46 | ||
47 | #define STK1160_MIN_PKT_SIZE 3072 | 47 | #define STK1160_MIN_PKT_SIZE 3072 |
48 | 48 | ||
49 | #define STK1160_MAX_INPUT 3 | 49 | #define STK1160_MAX_INPUT 4 |
50 | #define STK1160_SVIDEO_INPUT 4 | ||
50 | 51 | ||
51 | #define STK1160_I2C_TIMEOUT 100 | 52 | #define STK1160_I2C_TIMEOUT 100 |
52 | 53 | ||
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 5577381b5bf0..18a91fae6bc1 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c | |||
@@ -122,21 +122,27 @@ static struct vb2_ops uvc_queue_qops = { | |||
122 | .buf_finish = uvc_buffer_finish, | 122 | .buf_finish = uvc_buffer_finish, |
123 | }; | 123 | }; |
124 | 124 | ||
125 | void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, | 125 | int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, |
126 | int drop_corrupted) | 126 | int drop_corrupted) |
127 | { | 127 | { |
128 | int ret; | ||
129 | |||
128 | queue->queue.type = type; | 130 | queue->queue.type = type; |
129 | queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; | 131 | queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; |
130 | queue->queue.drv_priv = queue; | 132 | queue->queue.drv_priv = queue; |
131 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); | 133 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); |
132 | queue->queue.ops = &uvc_queue_qops; | 134 | queue->queue.ops = &uvc_queue_qops; |
133 | queue->queue.mem_ops = &vb2_vmalloc_memops; | 135 | queue->queue.mem_ops = &vb2_vmalloc_memops; |
134 | vb2_queue_init(&queue->queue); | 136 | ret = vb2_queue_init(&queue->queue); |
137 | if (ret) | ||
138 | return ret; | ||
135 | 139 | ||
136 | mutex_init(&queue->mutex); | 140 | mutex_init(&queue->mutex); |
137 | spin_lock_init(&queue->irqlock); | 141 | spin_lock_init(&queue->irqlock); |
138 | INIT_LIST_HEAD(&queue->irqqueue); | 142 | INIT_LIST_HEAD(&queue->irqqueue); |
139 | queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; | 143 | queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; |
144 | |||
145 | return 0; | ||
140 | } | 146 | } |
141 | 147 | ||
142 | /* ----------------------------------------------------------------------------- | 148 | /* ----------------------------------------------------------------------------- |
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 1c15b4227bdb..57c3076a4625 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c | |||
@@ -1755,7 +1755,9 @@ int uvc_video_init(struct uvc_streaming *stream) | |||
1755 | atomic_set(&stream->active, 0); | 1755 | atomic_set(&stream->active, 0); |
1756 | 1756 | ||
1757 | /* Initialize the video buffers queue. */ | 1757 | /* Initialize the video buffers queue. */ |
1758 | uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param); | 1758 | ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param); |
1759 | if (ret) | ||
1760 | return ret; | ||
1759 | 1761 | ||
1760 | /* Alternate setting 0 should be the default, yet the XBox Live Vision | 1762 | /* Alternate setting 0 should be the default, yet the XBox Live Vision |
1761 | * Cam (and possibly other devices) crash or otherwise misbehave if | 1763 | * Cam (and possibly other devices) crash or otherwise misbehave if |
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 3764040475bb..af216ec45e39 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h | |||
@@ -600,7 +600,7 @@ extern struct uvc_driver uvc_driver; | |||
600 | extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); | 600 | extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); |
601 | 601 | ||
602 | /* Video buffers queue management. */ | 602 | /* Video buffers queue management. */ |
603 | extern void uvc_queue_init(struct uvc_video_queue *queue, | 603 | extern int uvc_queue_init(struct uvc_video_queue *queue, |
604 | enum v4l2_buf_type type, int drop_corrupted); | 604 | enum v4l2_buf_type type, int drop_corrupted); |
605 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, | 605 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, |
606 | struct v4l2_requestbuffers *rb); | 606 | struct v4l2_requestbuffers *rb); |
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 631cdc0e0bda..f6ee201d9347 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
@@ -384,6 +384,25 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
384 | "Extended SAR", | 384 | "Extended SAR", |
385 | NULL, | 385 | NULL, |
386 | }; | 386 | }; |
387 | static const char * const h264_fp_arrangement_type[] = { | ||
388 | "Checkerboard", | ||
389 | "Column", | ||
390 | "Row", | ||
391 | "Side by Side", | ||
392 | "Top Bottom", | ||
393 | "Temporal", | ||
394 | NULL, | ||
395 | }; | ||
396 | static const char * const h264_fmo_map_type[] = { | ||
397 | "Interleaved Slices", | ||
398 | "Scattered Slices", | ||
399 | "Foreground with Leftover", | ||
400 | "Box Out", | ||
401 | "Raster Scan", | ||
402 | "Wipe Scan", | ||
403 | "Explicit", | ||
404 | NULL, | ||
405 | }; | ||
387 | static const char * const mpeg_mpeg4_level[] = { | 406 | static const char * const mpeg_mpeg4_level[] = { |
388 | "0", | 407 | "0", |
389 | "0b", | 408 | "0b", |
@@ -508,6 +527,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
508 | return h264_profile; | 527 | return h264_profile; |
509 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: | 528 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: |
510 | return vui_sar_idc; | 529 | return vui_sar_idc; |
530 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: | ||
531 | return h264_fp_arrangement_type; | ||
532 | case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: | ||
533 | return h264_fmo_map_type; | ||
511 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: | 534 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
512 | return mpeg_mpeg4_level; | 535 | return mpeg_mpeg4_level; |
513 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | 536 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
@@ -643,6 +666,22 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
643 | case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: return "Horizontal Size of SAR"; | 666 | case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: return "Horizontal Size of SAR"; |
644 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable"; | 667 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable"; |
645 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC"; | 668 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC"; |
669 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: return "H264 Enable Frame Packing SEI"; | ||
670 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0: return "H264 Set Curr. Frame as Frame0"; | ||
671 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: return "H264 FP Arrangement Type"; | ||
672 | case V4L2_CID_MPEG_VIDEO_H264_FMO: return "H264 Flexible MB Ordering"; | ||
673 | case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: return "H264 Map Type for FMO"; | ||
674 | case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP: return "H264 FMO Number of Slice Groups"; | ||
675 | case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION: return "H264 FMO Direction of Change"; | ||
676 | case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE: return "H264 FMO Size of 1st Slice Grp"; | ||
677 | case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH: return "H264 FMO No. of Consecutive MBs"; | ||
678 | case V4L2_CID_MPEG_VIDEO_H264_ASO: return "H264 Arbitrary Slice Ordering"; | ||
679 | case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER: return "H264 ASO Slice Order"; | ||
680 | case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING: return "Enable H264 Hierarchical Coding"; | ||
681 | case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: return "H264 Hierarchical Coding Type"; | ||
682 | case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers"; | ||
683 | case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP: | ||
684 | return "H264 Set QP Value for HC Layers"; | ||
646 | case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; | 685 | case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; |
647 | case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value"; | 686 | case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value"; |
648 | case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value"; | 687 | case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value"; |
@@ -657,6 +696,7 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
657 | case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; | 696 | case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; |
658 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; | 697 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; |
659 | case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; | 698 | case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; |
699 | case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; | ||
660 | 700 | ||
661 | /* CAMERA controls */ | 701 | /* CAMERA controls */ |
662 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 702 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
@@ -749,6 +789,7 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
749 | case V4L2_CID_IMAGE_PROC_CLASS: return "Image Processing Controls"; | 789 | case V4L2_CID_IMAGE_PROC_CLASS: return "Image Processing Controls"; |
750 | case V4L2_CID_LINK_FREQ: return "Link Frequency"; | 790 | case V4L2_CID_LINK_FREQ: return "Link Frequency"; |
751 | case V4L2_CID_PIXEL_RATE: return "Pixel Rate"; | 791 | case V4L2_CID_PIXEL_RATE: return "Pixel Rate"; |
792 | case V4L2_CID_TEST_PATTERN: return "Test Pattern"; | ||
752 | 793 | ||
753 | /* DV controls */ | 794 | /* DV controls */ |
754 | case V4L2_CID_DV_CLASS: return "Digital Video Controls"; | 795 | case V4L2_CID_DV_CLASS: return "Digital Video Controls"; |
@@ -853,6 +894,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
853 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: | 894 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: |
854 | case V4L2_CID_MPEG_VIDEO_H264_PROFILE: | 895 | case V4L2_CID_MPEG_VIDEO_H264_PROFILE: |
855 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: | 896 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: |
897 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: | ||
898 | case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: | ||
856 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: | 899 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
857 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | 900 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
858 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: | 901 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: |
@@ -862,6 +905,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
862 | case V4L2_CID_DV_TX_MODE: | 905 | case V4L2_CID_DV_TX_MODE: |
863 | case V4L2_CID_DV_TX_RGB_RANGE: | 906 | case V4L2_CID_DV_TX_RGB_RANGE: |
864 | case V4L2_CID_DV_RX_RGB_RANGE: | 907 | case V4L2_CID_DV_RX_RGB_RANGE: |
908 | case V4L2_CID_TEST_PATTERN: | ||
865 | *type = V4L2_CTRL_TYPE_MENU; | 909 | *type = V4L2_CTRL_TYPE_MENU; |
866 | break; | 910 | break; |
867 | case V4L2_CID_LINK_FREQ: | 911 | case V4L2_CID_LINK_FREQ: |
@@ -1648,6 +1692,36 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | |||
1648 | } | 1692 | } |
1649 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); | 1693 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); |
1650 | 1694 | ||
1695 | /* Helper function for standard menu controls with driver defined menu */ | ||
1696 | struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, | ||
1697 | const struct v4l2_ctrl_ops *ops, u32 id, s32 max, | ||
1698 | s32 mask, s32 def, const char * const *qmenu) | ||
1699 | { | ||
1700 | enum v4l2_ctrl_type type; | ||
1701 | const char *name; | ||
1702 | u32 flags; | ||
1703 | s32 step; | ||
1704 | s32 min; | ||
1705 | |||
1706 | /* v4l2_ctrl_new_std_menu_items() should only be called for | ||
1707 | * standard controls without a standard menu. | ||
1708 | */ | ||
1709 | if (v4l2_ctrl_get_menu(id)) { | ||
1710 | handler_set_err(hdl, -EINVAL); | ||
1711 | return NULL; | ||
1712 | } | ||
1713 | |||
1714 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); | ||
1715 | if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) { | ||
1716 | handler_set_err(hdl, -EINVAL); | ||
1717 | return NULL; | ||
1718 | } | ||
1719 | return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def, | ||
1720 | flags, qmenu, NULL, NULL); | ||
1721 | |||
1722 | } | ||
1723 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); | ||
1724 | |||
1651 | /* Helper function for standard integer menu controls */ | 1725 | /* Helper function for standard integer menu controls */ |
1652 | struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, | 1726 | struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, |
1653 | const struct v4l2_ctrl_ops *ops, | 1727 | const struct v4l2_ctrl_ops *ops, |
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 9d3e46c446ad..8f388ff31ebb 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c | |||
@@ -157,8 +157,7 @@ static const char *v4l2_memory_names[] = { | |||
157 | [V4L2_MEMORY_OVERLAY] = "overlay", | 157 | [V4L2_MEMORY_OVERLAY] = "overlay", |
158 | }; | 158 | }; |
159 | 159 | ||
160 | #define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \ | 160 | #define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown") |
161 | arr[a] : "unknown") | ||
162 | 161 | ||
163 | /* ------------------------------------------------------------------ */ | 162 | /* ------------------------------------------------------------------ */ |
164 | /* debug help functions */ | 163 | /* debug help functions */ |
@@ -2188,6 +2187,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, | |||
2188 | int ret = 0; | 2187 | int ret = 0; |
2189 | 2188 | ||
2190 | switch (cmd) { | 2189 | switch (cmd) { |
2190 | case VIDIOC_PREPARE_BUF: | ||
2191 | case VIDIOC_QUERYBUF: | 2191 | case VIDIOC_QUERYBUF: |
2192 | case VIDIOC_QBUF: | 2192 | case VIDIOC_QBUF: |
2193 | case VIDIOC_DQBUF: { | 2193 | case VIDIOC_DQBUF: { |
@@ -2211,6 +2211,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, | |||
2211 | struct v4l2_subdev_edid *edid = parg; | 2211 | struct v4l2_subdev_edid *edid = parg; |
2212 | 2212 | ||
2213 | if (edid->blocks) { | 2213 | if (edid->blocks) { |
2214 | if (edid->blocks > 256) { | ||
2215 | ret = -EINVAL; | ||
2216 | break; | ||
2217 | } | ||
2214 | *user_ptr = (void __user *)edid->edid; | 2218 | *user_ptr = (void __user *)edid->edid; |
2215 | *kernel_ptr = (void *)&edid->edid; | 2219 | *kernel_ptr = (void *)&edid->edid; |
2216 | *array_size = edid->blocks * 128; | 2220 | *array_size = edid->blocks * 128; |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index e6a26b433e87..432df119af27 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
@@ -276,6 +276,9 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) | |||
276 | */ | 276 | */ |
277 | static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b) | 277 | static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b) |
278 | { | 278 | { |
279 | if (!V4L2_TYPE_IS_MULTIPLANAR(b->type)) | ||
280 | return 0; | ||
281 | |||
279 | /* Is memory for copying plane information present? */ | 282 | /* Is memory for copying plane information present? */ |
280 | if (NULL == b->m.planes) { | 283 | if (NULL == b->m.planes) { |
281 | dprintk(1, "Multi-planar buffer passed but " | 284 | dprintk(1, "Multi-planar buffer passed but " |
@@ -331,10 +334,9 @@ static bool __buffers_in_use(struct vb2_queue *q) | |||
331 | * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be | 334 | * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be |
332 | * returned to userspace | 335 | * returned to userspace |
333 | */ | 336 | */ |
334 | static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) | 337 | static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) |
335 | { | 338 | { |
336 | struct vb2_queue *q = vb->vb2_queue; | 339 | struct vb2_queue *q = vb->vb2_queue; |
337 | int ret; | ||
338 | 340 | ||
339 | /* Copy back data such as timestamp, flags, etc. */ | 341 | /* Copy back data such as timestamp, flags, etc. */ |
340 | memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m)); | 342 | memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m)); |
@@ -342,14 +344,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) | |||
342 | b->reserved = vb->v4l2_buf.reserved; | 344 | b->reserved = vb->v4l2_buf.reserved; |
343 | 345 | ||
344 | if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) { | 346 | if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) { |
345 | ret = __verify_planes_array(vb, b); | ||
346 | if (ret) | ||
347 | return ret; | ||
348 | |||
349 | /* | 347 | /* |
350 | * Fill in plane-related data if userspace provided an array | 348 | * Fill in plane-related data if userspace provided an array |
351 | * for it. The memory and size is verified above. | 349 | * for it. The caller has already verified memory and size. |
352 | */ | 350 | */ |
351 | b->length = vb->num_planes; | ||
353 | memcpy(b->m.planes, vb->v4l2_planes, | 352 | memcpy(b->m.planes, vb->v4l2_planes, |
354 | b->length * sizeof(struct v4l2_plane)); | 353 | b->length * sizeof(struct v4l2_plane)); |
355 | } else { | 354 | } else { |
@@ -391,8 +390,6 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) | |||
391 | 390 | ||
392 | if (__buffer_in_use(q, vb)) | 391 | if (__buffer_in_use(q, vb)) |
393 | b->flags |= V4L2_BUF_FLAG_MAPPED; | 392 | b->flags |= V4L2_BUF_FLAG_MAPPED; |
394 | |||
395 | return 0; | ||
396 | } | 393 | } |
397 | 394 | ||
398 | /** | 395 | /** |
@@ -411,6 +408,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) | |||
411 | int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) | 408 | int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) |
412 | { | 409 | { |
413 | struct vb2_buffer *vb; | 410 | struct vb2_buffer *vb; |
411 | int ret; | ||
414 | 412 | ||
415 | if (b->type != q->type) { | 413 | if (b->type != q->type) { |
416 | dprintk(1, "querybuf: wrong buffer type\n"); | 414 | dprintk(1, "querybuf: wrong buffer type\n"); |
@@ -422,8 +420,10 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
422 | return -EINVAL; | 420 | return -EINVAL; |
423 | } | 421 | } |
424 | vb = q->bufs[b->index]; | 422 | vb = q->bufs[b->index]; |
425 | 423 | ret = __verify_planes_array(vb, b); | |
426 | return __fill_v4l2_buffer(vb, b); | 424 | if (!ret) |
425 | __fill_v4l2_buffer(vb, b); | ||
426 | return ret; | ||
427 | } | 427 | } |
428 | EXPORT_SYMBOL(vb2_querybuf); | 428 | EXPORT_SYMBOL(vb2_querybuf); |
429 | 429 | ||
@@ -813,24 +813,16 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) | |||
813 | EXPORT_SYMBOL_GPL(vb2_buffer_done); | 813 | EXPORT_SYMBOL_GPL(vb2_buffer_done); |
814 | 814 | ||
815 | /** | 815 | /** |
816 | * __fill_vb2_buffer() - fill a vb2_buffer with information provided in | 816 | * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a |
817 | * a v4l2_buffer by the userspace | 817 | * v4l2_buffer by the userspace. The caller has already verified that struct |
818 | * v4l2_buffer has a valid number of planes. | ||
818 | */ | 819 | */ |
819 | static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b, | 820 | static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b, |
820 | struct v4l2_plane *v4l2_planes) | 821 | struct v4l2_plane *v4l2_planes) |
821 | { | 822 | { |
822 | unsigned int plane; | 823 | unsigned int plane; |
823 | int ret; | ||
824 | 824 | ||
825 | if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { | 825 | if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { |
826 | /* | ||
827 | * Verify that the userspace gave us a valid array for | ||
828 | * plane information. | ||
829 | */ | ||
830 | ret = __verify_planes_array(vb, b); | ||
831 | if (ret) | ||
832 | return ret; | ||
833 | |||
834 | /* Fill in driver-provided information for OUTPUT types */ | 826 | /* Fill in driver-provided information for OUTPUT types */ |
835 | if (V4L2_TYPE_IS_OUTPUT(b->type)) { | 827 | if (V4L2_TYPE_IS_OUTPUT(b->type)) { |
836 | /* | 828 | /* |
@@ -872,8 +864,6 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b, | |||
872 | vb->v4l2_buf.field = b->field; | 864 | vb->v4l2_buf.field = b->field; |
873 | vb->v4l2_buf.timestamp = b->timestamp; | 865 | vb->v4l2_buf.timestamp = b->timestamp; |
874 | vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS; | 866 | vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS; |
875 | |||
876 | return 0; | ||
877 | } | 867 | } |
878 | 868 | ||
879 | /** | 869 | /** |
@@ -888,10 +878,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
888 | int ret; | 878 | int ret; |
889 | int write = !V4L2_TYPE_IS_OUTPUT(q->type); | 879 | int write = !V4L2_TYPE_IS_OUTPUT(q->type); |
890 | 880 | ||
891 | /* Verify and copy relevant information provided by the userspace */ | 881 | /* Copy relevant information provided by the userspace */ |
892 | ret = __fill_vb2_buffer(vb, b, planes); | 882 | __fill_vb2_buffer(vb, b, planes); |
893 | if (ret) | ||
894 | return ret; | ||
895 | 883 | ||
896 | for (plane = 0; plane < vb->num_planes; ++plane) { | 884 | for (plane = 0; plane < vb->num_planes; ++plane) { |
897 | /* Skip the plane if already verified */ | 885 | /* Skip the plane if already verified */ |
@@ -966,7 +954,8 @@ err: | |||
966 | */ | 954 | */ |
967 | static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) | 955 | static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) |
968 | { | 956 | { |
969 | return __fill_vb2_buffer(vb, b, vb->v4l2_planes); | 957 | __fill_vb2_buffer(vb, b, vb->v4l2_planes); |
958 | return 0; | ||
970 | } | 959 | } |
971 | 960 | ||
972 | /** | 961 | /** |
@@ -1059,7 +1048,9 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1059 | dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state); | 1048 | dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state); |
1060 | return -EINVAL; | 1049 | return -EINVAL; |
1061 | } | 1050 | } |
1062 | 1051 | ret = __verify_planes_array(vb, b); | |
1052 | if (ret < 0) | ||
1053 | return ret; | ||
1063 | ret = __buf_prepare(vb, b); | 1054 | ret = __buf_prepare(vb, b); |
1064 | if (ret < 0) | 1055 | if (ret < 0) |
1065 | return ret; | 1056 | return ret; |
@@ -1147,6 +1138,9 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1147 | ret = -EINVAL; | 1138 | ret = -EINVAL; |
1148 | goto unlock; | 1139 | goto unlock; |
1149 | } | 1140 | } |
1141 | ret = __verify_planes_array(vb, b); | ||
1142 | if (ret) | ||
1143 | goto unlock; | ||
1150 | 1144 | ||
1151 | switch (vb->state) { | 1145 | switch (vb->state) { |
1152 | case VB2_BUF_STATE_DEQUEUED: | 1146 | case VB2_BUF_STATE_DEQUEUED: |
@@ -1243,8 +1237,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) | |||
1243 | * the locks or return an error if one occurred. | 1237 | * the locks or return an error if one occurred. |
1244 | */ | 1238 | */ |
1245 | call_qop(q, wait_finish, q); | 1239 | call_qop(q, wait_finish, q); |
1246 | if (ret) | 1240 | if (ret) { |
1241 | dprintk(1, "Sleep was interrupted\n"); | ||
1247 | return ret; | 1242 | return ret; |
1243 | } | ||
1248 | } | 1244 | } |
1249 | return 0; | 1245 | return 0; |
1250 | } | 1246 | } |
@@ -1255,7 +1251,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) | |||
1255 | * Will sleep if required for nonblocking == false. | 1251 | * Will sleep if required for nonblocking == false. |
1256 | */ | 1252 | */ |
1257 | static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb, | 1253 | static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb, |
1258 | int nonblocking) | 1254 | struct v4l2_buffer *b, int nonblocking) |
1259 | { | 1255 | { |
1260 | unsigned long flags; | 1256 | unsigned long flags; |
1261 | int ret; | 1257 | int ret; |
@@ -1273,10 +1269,16 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb, | |||
1273 | */ | 1269 | */ |
1274 | spin_lock_irqsave(&q->done_lock, flags); | 1270 | spin_lock_irqsave(&q->done_lock, flags); |
1275 | *vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry); | 1271 | *vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry); |
1276 | list_del(&(*vb)->done_entry); | 1272 | /* |
1273 | * Only remove the buffer from done_list if v4l2_buffer can handle all | ||
1274 | * the planes. | ||
1275 | */ | ||
1276 | ret = __verify_planes_array(*vb, b); | ||
1277 | if (!ret) | ||
1278 | list_del(&(*vb)->done_entry); | ||
1277 | spin_unlock_irqrestore(&q->done_lock, flags); | 1279 | spin_unlock_irqrestore(&q->done_lock, flags); |
1278 | 1280 | ||
1279 | return 0; | 1281 | return ret; |
1280 | } | 1282 | } |
1281 | 1283 | ||
1282 | /** | 1284 | /** |
@@ -1335,12 +1337,9 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) | |||
1335 | dprintk(1, "dqbuf: invalid buffer type\n"); | 1337 | dprintk(1, "dqbuf: invalid buffer type\n"); |
1336 | return -EINVAL; | 1338 | return -EINVAL; |
1337 | } | 1339 | } |
1338 | 1340 | ret = __vb2_get_done_vb(q, &vb, b, nonblocking); | |
1339 | ret = __vb2_get_done_vb(q, &vb, nonblocking); | 1341 | if (ret < 0) |
1340 | if (ret < 0) { | ||
1341 | dprintk(1, "dqbuf: error getting next done buffer\n"); | ||
1342 | return ret; | 1342 | return ret; |
1343 | } | ||
1344 | 1343 | ||
1345 | ret = call_qop(q, buf_finish, vb); | 1344 | ret = call_qop(q, buf_finish, vb); |
1346 | if (ret) { | 1345 | if (ret) { |