mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 21:54:11 +08:00
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "This series include: - a new Remote Controller driver for ST SoC with the corresponding DT bindings - a new frontend (cx24117) - a new I2C camera flash driver (lm3560) - a new mem2mem driver for TI SoC (ti-vpe) - support for Raphael r828d added to r820t driver - some improvements on buffer allocation at VB2 core - usual driver fixes and improvements PS this time, we have a smaller number of patches. While it is hard to pinpoint to the reasons, I believe that it is mainly due to: 1) there are several patch series ready, but depending on DT review. I decided to grant some extra time for DT maintainers to look on it, as they're expecting to have more time with the changes agreed during ARM mini-summit and KS. If they can't review in time for 3.14, I'll review myself and apply for the next merge window. 2) I suspect that having both LinuxCon EU and LinuxCon NA happening during the same merge window affected the development productivity, as several core media developers participated on both events" * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (151 commits) [media] media: st-rc: Add ST remote control driver [media] gpio-ir-recv: Include linux/of.h header [media] tvp7002: Include linux/of.h header [media] tvp514x: Include linux/of.h header [media] ths8200: Include linux/of.h header [media] adv7343: Include linux/of.h header [media] v4l: Fix typo in v4l2_subdev_get_try_crop() [media] media: i2c: add driver for dual LED Flash, lm3560 [media] rtl28xxu: add 15f4:0131 Astrometa DVB-T2 [media] rtl28xxu: add RTL2832P + R828D support [media] rtl2832: add new tuner R828D [media] r820t: add support for R828D [media] media/i2c: ths8200: fix build failure with gcc 4.5.4 [media] Add support for KWorld UB435-Q V2 [media] staging/media: fix msi3101 build errors [media] ddbridge: Remove casting the return value which is a void pointer [media] ngene: Remove casting the return value which is a void pointer [media] dm1105: remove unneeded not-null test [media] sh_mobile_ceu_camera: remove deprecated IRQF_DISABLED [media] media: rcar_vin: Add preliminary r8a7790 support ...
This commit is contained in:
commit
a310410f61
29
Documentation/devicetree/bindings/media/st-rc.txt
Normal file
29
Documentation/devicetree/bindings/media/st-rc.txt
Normal file
@ -0,0 +1,29 @@
|
||||
Device-Tree bindings for ST IRB IP
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "st,comms-irb".
|
||||
- reg: Base physical address of the controller and length of memory
|
||||
mapped region.
|
||||
- interrupts: interrupt-specifier for the sole interrupt generated by
|
||||
the device. The interrupt specifier format depends on the interrupt
|
||||
controller parent.
|
||||
- rx-mode: can be "infrared" or "uhf". This property specifies the L1
|
||||
protocol used for receiving remote control signals. rx-mode should
|
||||
be present iff the rx pins are wired up.
|
||||
- tx-mode: should be "infrared". This property specifies the L1
|
||||
protocol used for transmitting remote control signals. tx-mode should
|
||||
be present iff the tx pins are wired up.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names, pinctrl-0: the pincontrol settings to configure muxing
|
||||
properly for IRB pins.
|
||||
- clocks : phandle with clock-specifier pair for IRB.
|
||||
|
||||
Example node:
|
||||
|
||||
rc: rc@fe518000 {
|
||||
compatible = "st,comms-irb";
|
||||
reg = <0xfe518000 0x234>;
|
||||
interrupts = <0 203 0>;
|
||||
rx-mode = "infrared";
|
||||
};
|
@ -85,7 +85,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *
|
||||
while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
|
||||
mdelay(1);
|
||||
retries--;
|
||||
};
|
||||
}
|
||||
|
||||
if (retries == 0)
|
||||
printk("%s: SRAM timeout\n", __func__);
|
||||
@ -110,7 +110,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
|
||||
while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
|
||||
mdelay(1);
|
||||
retries--;
|
||||
};
|
||||
}
|
||||
|
||||
if (retries == 0)
|
||||
printk("%s: SRAM timeout\n", __func__);
|
||||
@ -122,7 +122,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
|
||||
while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
|
||||
mdelay(1);
|
||||
retries--;
|
||||
};
|
||||
}
|
||||
|
||||
if (retries == 0)
|
||||
printk("%s: SRAM timeout\n", __func__);
|
||||
|
@ -411,7 +411,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
||||
saa7146_write(dev, MC2, 0xf8000000);
|
||||
|
||||
/* request an interrupt for the saa7146 */
|
||||
err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
|
||||
err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED,
|
||||
dev->name, dev);
|
||||
if (err < 0) {
|
||||
ERR("request_irq() failed\n");
|
||||
@ -524,8 +524,6 @@ static void saa7146_remove_one(struct pci_dev *pdev)
|
||||
DEB_EE("dev:%p\n", dev);
|
||||
|
||||
dev->ext->detach(dev);
|
||||
/* Zero the PCI drvdata after use. */
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
||||
/* shut down all video dma transfers */
|
||||
saa7146_write(dev, MC1, 0x00ff0000);
|
||||
|
@ -922,8 +922,8 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
|
||||
u32 i, *ptr;
|
||||
u8 *payload = firmware->payload;
|
||||
int rc = 0;
|
||||
firmware->start_address = le32_to_cpu(firmware->start_address);
|
||||
firmware->length = le32_to_cpu(firmware->length);
|
||||
firmware->start_address = le32_to_cpup((__le32 *)&firmware->start_address);
|
||||
firmware->length = le32_to_cpup((__le32 *)&firmware->length);
|
||||
|
||||
mem_address = firmware->start_address;
|
||||
|
||||
@ -982,7 +982,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
|
||||
if (rc < 0)
|
||||
goto exit_fw_download;
|
||||
|
||||
sms_err("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
|
||||
sms_debug("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
|
||||
calc_checksum);
|
||||
SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_VALIDITY_REQ,
|
||||
sizeof(msg->x_msg_header) +
|
||||
@ -1562,7 +1562,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
|
||||
{
|
||||
struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
|
||||
|
||||
sms_err("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
|
||||
sms_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
|
||||
validity->msg_data[0]);
|
||||
complete(&coredev->data_validity_done);
|
||||
break;
|
||||
|
@ -44,14 +44,14 @@ module_param_named(debug, sms_dbg, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
|
||||
|
||||
|
||||
u32 sms_to_guard_interval_table[] = {
|
||||
static u32 sms_to_guard_interval_table[] = {
|
||||
[0] = GUARD_INTERVAL_1_32,
|
||||
[1] = GUARD_INTERVAL_1_16,
|
||||
[2] = GUARD_INTERVAL_1_8,
|
||||
[3] = GUARD_INTERVAL_1_4,
|
||||
};
|
||||
|
||||
u32 sms_to_code_rate_table[] = {
|
||||
static u32 sms_to_code_rate_table[] = {
|
||||
[0] = FEC_1_2,
|
||||
[1] = FEC_2_3,
|
||||
[2] = FEC_3_4,
|
||||
@ -60,14 +60,14 @@ u32 sms_to_code_rate_table[] = {
|
||||
};
|
||||
|
||||
|
||||
u32 sms_to_hierarchy_table[] = {
|
||||
static u32 sms_to_hierarchy_table[] = {
|
||||
[0] = HIERARCHY_NONE,
|
||||
[1] = HIERARCHY_1,
|
||||
[2] = HIERARCHY_2,
|
||||
[3] = HIERARCHY_4,
|
||||
};
|
||||
|
||||
u32 sms_to_modulation_table[] = {
|
||||
static u32 sms_to_modulation_table[] = {
|
||||
[0] = QPSK,
|
||||
[1] = QAM_16,
|
||||
[2] = QAM_64,
|
||||
|
@ -476,7 +476,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
while (count--) {
|
||||
if (buf[0] == 0x47)
|
||||
@ -484,7 +486,7 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
buf += 188;
|
||||
}
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
|
||||
@ -519,8 +521,9 @@ static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
{
|
||||
int p = 0, i, j;
|
||||
const u8 *q;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
|
||||
i = demux->tsbufp;
|
||||
@ -564,7 +567,7 @@ static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
@ -581,11 +584,13 @@ EXPORT_SYMBOL(dvb_dmx_swfilter_204);
|
||||
|
||||
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_raw);
|
||||
|
||||
|
@ -200,6 +200,13 @@ config DVB_CX24116
|
||||
help
|
||||
A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX24117
|
||||
tristate "Conexant CX24117 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
A Dual DVB-S/S2 tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_SI21XX
|
||||
tristate "Silicon Labs SI21XX based"
|
||||
depends on DVB_CORE && I2C
|
||||
|
@ -76,6 +76,7 @@ obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
|
||||
obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
|
||||
obj-$(CONFIG_DVB_AF9013) += af9013.o
|
||||
obj-$(CONFIG_DVB_CX24116) += cx24116.o
|
||||
obj-$(CONFIG_DVB_CX24117) += cx24117.o
|
||||
obj-$(CONFIG_DVB_SI21XX) += si21xx.o
|
||||
obj-$(CONFIG_DVB_STV0288) += stv0288.o
|
||||
obj-$(CONFIG_DVB_STB6000) += stb6000.o
|
||||
|
@ -378,7 +378,7 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
|
||||
return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40);
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
|
||||
|
1650
drivers/media/dvb-frontends/cx24117.c
Normal file
1650
drivers/media/dvb-frontends/cx24117.c
Normal file
File diff suppressed because it is too large
Load Diff
47
drivers/media/dvb-frontends/cx24117.h
Normal file
47
drivers/media/dvb-frontends/cx24117.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Conexant cx24117/cx24132 - Dual DVBS/S2 Satellite demod/tuner driver
|
||||
|
||||
Copyright (C) 2013 Luis Alves <ljalvs@gmail.com>
|
||||
(based on cx24116.h by Steven Toth)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef CX24117_H
|
||||
#define CX24117_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
struct cx24117_config {
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_CX24117)
|
||||
extern struct dvb_frontend *cx24117_attach(
|
||||
const struct cx24117_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend *cx24117_attach(
|
||||
const struct cx24117_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CX24117_H */
|
@ -739,7 +739,7 @@ static int cx24123_set_voltage(struct dvb_frontend *fe,
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
|
||||
{
|
||||
.addr = i2c,
|
||||
.flags = 0,
|
||||
.len = sizeof(buf),
|
||||
.len = len + 1,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
@ -65,7 +65,7 @@ static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
|
||||
}, {
|
||||
.addr = i2c,
|
||||
.flags = I2C_M_RD,
|
||||
.len = sizeof(buf),
|
||||
.len = len,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
@ -649,9 +649,9 @@ static int dib9000_risc_debug_buf(struct dib9000_state *state, u16 * data, u8 si
|
||||
b[2 * (size - 2) - 1] = '\0'; /* Bullet proof the buffer */
|
||||
if (*b == '~') {
|
||||
b++;
|
||||
dprintk(b);
|
||||
dprintk("%s", b);
|
||||
} else
|
||||
dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<emtpy>");
|
||||
dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<empty>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,6 @@
|
||||
#define DRX_I2C_MODEFLAGS 0xC0
|
||||
#define DRX_I2C_FLAGS 0xF0
|
||||
|
||||
#ifndef SIZEOF_ARRAY
|
||||
#define SIZEOF_ARRAY(array) (sizeof((array))/sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#define DEFAULT_LOCK_TIMEOUT 1100
|
||||
|
||||
#define DRX_CHANNEL_AUTO 0
|
||||
@ -1018,7 +1014,7 @@ static int HI_CfgCommand(struct drxd_state *state)
|
||||
status = Write16(state, HI_RA_RAM_SRV_CMD__A,
|
||||
HI_RA_RAM_SRV_CMD_CONFIG, 0);
|
||||
else
|
||||
status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, 0);
|
||||
status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, NULL);
|
||||
mutex_unlock(&state->mutex);
|
||||
return status;
|
||||
}
|
||||
@ -1039,7 +1035,7 @@ static int HI_ResetCommand(struct drxd_state *state)
|
||||
status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A,
|
||||
HI_RA_RAM_SRV_RST_KEY_ACT, 0);
|
||||
if (status == 0)
|
||||
status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, 0);
|
||||
status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, NULL);
|
||||
mutex_unlock(&state->mutex);
|
||||
msleep(1);
|
||||
return status;
|
||||
@ -2837,7 +2833,7 @@ static int drxd_init(struct dvb_frontend *fe)
|
||||
int err = 0;
|
||||
|
||||
/* if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */
|
||||
return DRXD_init(state, 0, 0);
|
||||
return DRXD_init(state, NULL, 0);
|
||||
|
||||
err = DRXD_init(state, state->fw->data, state->fw->size);
|
||||
release_firmware(state->fw);
|
||||
@ -2973,7 +2969,7 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
|
||||
|
||||
mutex_init(&state->mutex);
|
||||
|
||||
if (Read16(state, 0, 0, 0) < 0)
|
||||
if (Read16(state, 0, NULL, 0) < 0)
|
||||
goto error;
|
||||
|
||||
state->frontend.ops = drxd_ops;
|
||||
|
@ -1083,7 +1083,7 @@ static int hi_cfg_command(struct drxk_state *state)
|
||||
SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0);
|
||||
status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, NULL);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
@ -2781,7 +2781,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge)
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0);
|
||||
status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, NULL);
|
||||
|
||||
error:
|
||||
if (status < 0)
|
||||
|
@ -489,6 +489,7 @@ static int rtl2832_init(struct dvb_frontend *fe)
|
||||
init = rtl2832_tuner_init_e4000;
|
||||
break;
|
||||
case RTL2832_TUNER_R820T:
|
||||
case RTL2832_TUNER_R828D:
|
||||
len = ARRAY_SIZE(rtl2832_tuner_init_r820t);
|
||||
init = rtl2832_tuner_init_r820t;
|
||||
break;
|
||||
|
@ -53,6 +53,7 @@ struct rtl2832_config {
|
||||
#define RTL2832_TUNER_E4000 0x27
|
||||
#define RTL2832_TUNER_FC0013 0x29
|
||||
#define RTL2832_TUNER_R820T 0x2a
|
||||
#define RTL2832_TUNER_R828D 0x2b
|
||||
u8 tuner;
|
||||
};
|
||||
|
||||
|
@ -189,7 +189,7 @@ static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t ton
|
||||
return tda8083_writereg (state, 0x29, 0x80);
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t voltage)
|
||||
@ -201,7 +201,7 @@ static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t vo
|
||||
return tda8083_writereg (state, 0x20, 0x11);
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_cmd_t burst)
|
||||
|
@ -31,6 +31,7 @@ struct ts2020_priv {
|
||||
struct i2c_adapter *i2c;
|
||||
u8 clk_out_div;
|
||||
u32 frequency;
|
||||
u32 frequency_div;
|
||||
};
|
||||
|
||||
static int ts2020_release(struct dvb_frontend *fe)
|
||||
@ -193,7 +194,7 @@ static int ts2020_set_params(struct dvb_frontend *fe)
|
||||
u8 lo = 0x01, div4 = 0x0;
|
||||
|
||||
/* Calculate frequency divider */
|
||||
if (frequency < 1060000) {
|
||||
if (frequency < priv->frequency_div) {
|
||||
lo |= 0x10;
|
||||
div4 = 0x1;
|
||||
ndiv = (frequency * 14 * 4) / TS2020_XTAL_FREQ;
|
||||
@ -340,8 +341,12 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
|
||||
priv->i2c_address = config->tuner_address;
|
||||
priv->i2c = i2c;
|
||||
priv->clk_out_div = config->clk_out_div;
|
||||
priv->frequency_div = config->frequency_div;
|
||||
fe->tuner_priv = priv;
|
||||
|
||||
if (!priv->frequency_div)
|
||||
priv->frequency_div = 1060000;
|
||||
|
||||
/* Wake Up the tuner */
|
||||
if ((0x03 & ts2020_readreg(fe, 0x00)) == 0x00) {
|
||||
ts2020_writereg(fe, 0x00, 0x01);
|
||||
|
@ -28,6 +28,7 @@
|
||||
struct ts2020_config {
|
||||
u8 tuner_address;
|
||||
u8 clk_out_div;
|
||||
u32 frequency_div;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DVB_TS2020)
|
||||
|
@ -621,6 +621,15 @@ config VIDEO_AS3645A
|
||||
This is a driver for the AS3645A and LM3555 flash controllers. It has
|
||||
build in control for flash, torch and indicator LEDs.
|
||||
|
||||
config VIDEO_LM3560
|
||||
tristate "LM3560 dual flash driver support"
|
||||
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
select REGMAP_I2C
|
||||
---help---
|
||||
This is a driver for the lm3560 dual flash controllers. It controls
|
||||
flash, torch LEDs.
|
||||
|
||||
comment "Video improvement chips"
|
||||
|
||||
config VIDEO_UPD64031A
|
||||
|
@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
|
||||
obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
|
||||
obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
|
||||
obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o
|
||||
obj-$(CONFIG_VIDEO_LM3560) += lm3560.o
|
||||
obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
|
||||
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
|
||||
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <media/adv7343.h>
|
||||
#include <media/v4l2-async.h>
|
||||
|
488
drivers/media/i2c/lm3560.c
Normal file
488
drivers/media/i2c/lm3560.c
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
* drivers/media/i2c/lm3560.c
|
||||
* General device driver for TI lm3560, FLASH LED Driver
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments
|
||||
*
|
||||
* Contact: Daniel Jeong <gshark.jeong@gmail.com>
|
||||
* Ldd-Mlp <ldd-mlp@list.ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/lm3560.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
/* registers definitions */
|
||||
#define REG_ENABLE 0x10
|
||||
#define REG_TORCH_BR 0xa0
|
||||
#define REG_FLASH_BR 0xb0
|
||||
#define REG_FLASH_TOUT 0xc0
|
||||
#define REG_FLAG 0xd0
|
||||
#define REG_CONFIG1 0xe0
|
||||
|
||||
/* Fault Mask */
|
||||
#define FAULT_TIMEOUT (1<<0)
|
||||
#define FAULT_OVERTEMP (1<<1)
|
||||
#define FAULT_SHORT_CIRCUIT (1<<2)
|
||||
|
||||
enum led_enable {
|
||||
MODE_SHDN = 0x0,
|
||||
MODE_TORCH = 0x2,
|
||||
MODE_FLASH = 0x3,
|
||||
};
|
||||
|
||||
/* struct lm3560_flash
|
||||
*
|
||||
* @pdata: platform data
|
||||
* @regmap: reg. map for i2c
|
||||
* @lock: muxtex for serial access.
|
||||
* @led_mode: V4L2 LED mode
|
||||
* @ctrls_led: V4L2 contols
|
||||
* @subdev_led: V4L2 subdev
|
||||
*/
|
||||
struct lm3560_flash {
|
||||
struct device *dev;
|
||||
struct lm3560_platform_data *pdata;
|
||||
struct regmap *regmap;
|
||||
struct mutex lock;
|
||||
|
||||
enum v4l2_flash_led_mode led_mode;
|
||||
struct v4l2_ctrl_handler ctrls_led[LM3560_LED_MAX];
|
||||
struct v4l2_subdev subdev_led[LM3560_LED_MAX];
|
||||
};
|
||||
|
||||
#define to_lm3560_flash(_ctrl, _no) \
|
||||
container_of(_ctrl->handler, struct lm3560_flash, ctrls_led[_no])
|
||||
|
||||
/* enable mode control */
|
||||
static int lm3560_mode_ctrl(struct lm3560_flash *flash)
|
||||
{
|
||||
int rval = -EINVAL;
|
||||
|
||||
switch (flash->led_mode) {
|
||||
case V4L2_FLASH_LED_MODE_NONE:
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x03, MODE_SHDN);
|
||||
break;
|
||||
case V4L2_FLASH_LED_MODE_TORCH:
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x03, MODE_TORCH);
|
||||
break;
|
||||
case V4L2_FLASH_LED_MODE_FLASH:
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x03, MODE_FLASH);
|
||||
break;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* led1/2 enable/disable */
|
||||
static int lm3560_enable_ctrl(struct lm3560_flash *flash,
|
||||
enum lm3560_led_id led_no, bool on)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (led_no == LM3560_LED0) {
|
||||
if (on == true)
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x08, 0x08);
|
||||
else
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x08, 0x00);
|
||||
} else {
|
||||
if (on == true)
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x10, 0x10);
|
||||
else
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_ENABLE, 0x10, 0x00);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* torch1/2 brightness control */
|
||||
static int lm3560_torch_brt_ctrl(struct lm3560_flash *flash,
|
||||
enum lm3560_led_id led_no, unsigned int brt)
|
||||
{
|
||||
int rval;
|
||||
u8 br_bits;
|
||||
|
||||
if (brt < LM3560_TORCH_BRT_MIN)
|
||||
return lm3560_enable_ctrl(flash, led_no, false);
|
||||
else
|
||||
rval = lm3560_enable_ctrl(flash, led_no, true);
|
||||
|
||||
br_bits = LM3560_TORCH_BRT_uA_TO_REG(brt);
|
||||
if (led_no == LM3560_LED0)
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_TORCH_BR, 0x07, br_bits);
|
||||
else
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_TORCH_BR, 0x38, br_bits << 3);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* flash1/2 brightness control */
|
||||
static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash,
|
||||
enum lm3560_led_id led_no, unsigned int brt)
|
||||
{
|
||||
int rval;
|
||||
u8 br_bits;
|
||||
|
||||
if (brt < LM3560_FLASH_BRT_MIN)
|
||||
return lm3560_enable_ctrl(flash, led_no, false);
|
||||
else
|
||||
rval = lm3560_enable_ctrl(flash, led_no, true);
|
||||
|
||||
br_bits = LM3560_FLASH_BRT_uA_TO_REG(brt);
|
||||
if (led_no == LM3560_LED0)
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_FLASH_BR, 0x0f, br_bits);
|
||||
else
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_FLASH_BR, 0xf0, br_bits << 4);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* V4L2 controls */
|
||||
static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
|
||||
{
|
||||
struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
|
||||
|
||||
mutex_lock(&flash->lock);
|
||||
|
||||
if (ctrl->id == V4L2_CID_FLASH_FAULT) {
|
||||
int rval;
|
||||
s32 fault = 0;
|
||||
unsigned int reg_val;
|
||||
rval = regmap_read(flash->regmap, REG_FLAG, ®_val);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
if (rval & FAULT_SHORT_CIRCUIT)
|
||||
fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
|
||||
if (rval & FAULT_OVERTEMP)
|
||||
fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
|
||||
if (rval & FAULT_TIMEOUT)
|
||||
fault |= V4L2_FLASH_FAULT_TIMEOUT;
|
||||
ctrl->cur.val = fault;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&flash->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
|
||||
{
|
||||
struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
|
||||
u8 tout_bits;
|
||||
int rval = -EINVAL;
|
||||
|
||||
mutex_lock(&flash->lock);
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_FLASH_LED_MODE:
|
||||
flash->led_mode = ctrl->val;
|
||||
if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
|
||||
rval = lm3560_mode_ctrl(flash);
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_STROBE_SOURCE:
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_CONFIG1, 0x04, (ctrl->val) << 2);
|
||||
if (rval < 0)
|
||||
goto err_out;
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_STROBE:
|
||||
if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
|
||||
return -EBUSY;
|
||||
flash->led_mode = V4L2_FLASH_LED_MODE_FLASH;
|
||||
rval = lm3560_mode_ctrl(flash);
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_STROBE_STOP:
|
||||
if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
|
||||
return -EBUSY;
|
||||
flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
|
||||
rval = lm3560_mode_ctrl(flash);
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_TIMEOUT:
|
||||
tout_bits = LM3560_FLASH_TOUT_ms_TO_REG(ctrl->val);
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_FLASH_TOUT, 0x1f, tout_bits);
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_INTENSITY:
|
||||
rval = lm3560_flash_brt_ctrl(flash, led_no, ctrl->val);
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_TORCH_INTENSITY:
|
||||
rval = lm3560_torch_brt_ctrl(flash, led_no, ctrl->val);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&flash->lock);
|
||||
err_out:
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int lm3560_led1_get_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return lm3560_get_ctrl(ctrl, LM3560_LED1);
|
||||
}
|
||||
|
||||
static int lm3560_led1_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return lm3560_set_ctrl(ctrl, LM3560_LED1);
|
||||
}
|
||||
|
||||
static int lm3560_led0_get_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return lm3560_get_ctrl(ctrl, LM3560_LED0);
|
||||
}
|
||||
|
||||
static int lm3560_led0_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return lm3560_set_ctrl(ctrl, LM3560_LED0);
|
||||
}
|
||||
|
||||
static const struct v4l2_ctrl_ops lm3560_led_ctrl_ops[LM3560_LED_MAX] = {
|
||||
[LM3560_LED0] = {
|
||||
.g_volatile_ctrl = lm3560_led0_get_ctrl,
|
||||
.s_ctrl = lm3560_led0_set_ctrl,
|
||||
},
|
||||
[LM3560_LED1] = {
|
||||
.g_volatile_ctrl = lm3560_led1_get_ctrl,
|
||||
.s_ctrl = lm3560_led1_set_ctrl,
|
||||
}
|
||||
};
|
||||
|
||||
static int lm3560_init_controls(struct lm3560_flash *flash,
|
||||
enum lm3560_led_id led_no)
|
||||
{
|
||||
struct v4l2_ctrl *fault;
|
||||
u32 max_flash_brt = flash->pdata->max_flash_brt[led_no];
|
||||
u32 max_torch_brt = flash->pdata->max_torch_brt[led_no];
|
||||
struct v4l2_ctrl_handler *hdl = &flash->ctrls_led[led_no];
|
||||
const struct v4l2_ctrl_ops *ops = &lm3560_led_ctrl_ops[led_no];
|
||||
|
||||
v4l2_ctrl_handler_init(hdl, 8);
|
||||
/* flash mode */
|
||||
v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE,
|
||||
V4L2_FLASH_LED_MODE_TORCH, ~0x7,
|
||||
V4L2_FLASH_LED_MODE_NONE);
|
||||
flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
|
||||
|
||||
/* flash source */
|
||||
v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_STROBE_SOURCE,
|
||||
0x1, ~0x3, V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
|
||||
|
||||
/* flash strobe */
|
||||
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
|
||||
/* flash strobe stop */
|
||||
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
|
||||
|
||||
/* flash strobe timeout */
|
||||
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT,
|
||||
LM3560_FLASH_TOUT_MIN,
|
||||
flash->pdata->max_flash_timeout,
|
||||
LM3560_FLASH_TOUT_STEP,
|
||||
flash->pdata->max_flash_timeout);
|
||||
|
||||
/* flash brt */
|
||||
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY,
|
||||
LM3560_FLASH_BRT_MIN, max_flash_brt,
|
||||
LM3560_FLASH_BRT_STEP, max_flash_brt);
|
||||
|
||||
/* torch brt */
|
||||
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY,
|
||||
LM3560_TORCH_BRT_MIN, max_torch_brt,
|
||||
LM3560_TORCH_BRT_STEP, max_torch_brt);
|
||||
|
||||
/* fault */
|
||||
fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0,
|
||||
V4L2_FLASH_FAULT_OVER_VOLTAGE
|
||||
| V4L2_FLASH_FAULT_OVER_TEMPERATURE
|
||||
| V4L2_FLASH_FAULT_SHORT_CIRCUIT
|
||||
| V4L2_FLASH_FAULT_TIMEOUT, 0, 0);
|
||||
if (fault != NULL)
|
||||
fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
|
||||
if (hdl->error)
|
||||
return hdl->error;
|
||||
|
||||
flash->subdev_led[led_no].ctrl_handler = hdl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* initialize device */
|
||||
static const struct v4l2_subdev_ops lm3560_ops = {
|
||||
.core = NULL,
|
||||
};
|
||||
|
||||
static const struct regmap_config lm3560_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0xFF,
|
||||
};
|
||||
|
||||
static int lm3560_subdev_init(struct lm3560_flash *flash,
|
||||
enum lm3560_led_id led_no, char *led_name)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(flash->dev);
|
||||
int rval;
|
||||
|
||||
v4l2_i2c_subdev_init(&flash->subdev_led[led_no], client, &lm3560_ops);
|
||||
flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
strcpy(flash->subdev_led[led_no].name, led_name);
|
||||
rval = lm3560_init_controls(flash, led_no);
|
||||
if (rval)
|
||||
goto err_out;
|
||||
rval = media_entity_init(&flash->subdev_led[led_no].entity, 0, NULL, 0);
|
||||
if (rval < 0)
|
||||
goto err_out;
|
||||
flash->subdev_led[led_no].entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
|
||||
|
||||
return rval;
|
||||
|
||||
err_out:
|
||||
v4l2_ctrl_handler_free(&flash->ctrls_led[led_no]);
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int lm3560_init_device(struct lm3560_flash *flash)
|
||||
{
|
||||
int rval;
|
||||
unsigned int reg_val;
|
||||
|
||||
/* set peak current */
|
||||
rval = regmap_update_bits(flash->regmap,
|
||||
REG_FLASH_TOUT, 0x60, flash->pdata->peak);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
/* output disable */
|
||||
flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
|
||||
rval = lm3560_mode_ctrl(flash);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
/* Reset faults */
|
||||
rval = regmap_read(flash->regmap, REG_FLAG, ®_val);
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int lm3560_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *devid)
|
||||
{
|
||||
struct lm3560_flash *flash;
|
||||
struct lm3560_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
int rval;
|
||||
|
||||
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
|
||||
if (flash == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
flash->regmap = devm_regmap_init_i2c(client, &lm3560_regmap);
|
||||
if (IS_ERR(flash->regmap)) {
|
||||
rval = PTR_ERR(flash->regmap);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* if there is no platform data, use chip default value */
|
||||
if (pdata == NULL) {
|
||||
pdata =
|
||||
kzalloc(sizeof(struct lm3560_platform_data), GFP_KERNEL);
|
||||
if (pdata == NULL)
|
||||
return -ENODEV;
|
||||
pdata->peak = LM3560_PEAK_3600mA;
|
||||
pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
|
||||
/* led 1 */
|
||||
pdata->max_flash_brt[LM3560_LED0] = LM3560_FLASH_BRT_MAX;
|
||||
pdata->max_torch_brt[LM3560_LED0] = LM3560_TORCH_BRT_MAX;
|
||||
/* led 2 */
|
||||
pdata->max_flash_brt[LM3560_LED1] = LM3560_FLASH_BRT_MAX;
|
||||
pdata->max_torch_brt[LM3560_LED1] = LM3560_TORCH_BRT_MAX;
|
||||
}
|
||||
flash->pdata = pdata;
|
||||
flash->dev = &client->dev;
|
||||
mutex_init(&flash->lock);
|
||||
|
||||
rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0");
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1");
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
rval = lm3560_init_device(flash);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm3560_remove(struct i2c_client *client)
|
||||
{
|
||||
struct v4l2_subdev *subdev = i2c_get_clientdata(client);
|
||||
struct lm3560_flash *flash = container_of(subdev, struct lm3560_flash,
|
||||
subdev_led[LM3560_LED_MAX]);
|
||||
unsigned int i;
|
||||
|
||||
for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) {
|
||||
v4l2_device_unregister_subdev(&flash->subdev_led[i]);
|
||||
v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
|
||||
media_entity_cleanup(&flash->subdev_led[i].entity);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm3560_id_table[] = {
|
||||
{LM3560_NAME, 0},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, lm3560_id_table);
|
||||
|
||||
static struct i2c_driver lm3560_i2c_driver = {
|
||||
.driver = {
|
||||
.name = LM3560_NAME,
|
||||
.pm = NULL,
|
||||
},
|
||||
.probe = lm3560_probe,
|
||||
.remove = lm3560_remove,
|
||||
.id_table = lm3560_id_table,
|
||||
};
|
||||
|
||||
module_i2c_driver(lm3560_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
|
||||
MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
|
||||
MODULE_DESCRIPTION("Texas Instruments LM3560 LED flash driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -451,7 +451,9 @@ static int imx074_probe(struct i2c_client *client,
|
||||
if (ret < 0)
|
||||
goto eprobe;
|
||||
|
||||
return v4l2_async_register_subdev(&priv->subdev);
|
||||
ret = v4l2_async_register_subdev(&priv->subdev);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
epwrinit:
|
||||
eprobe:
|
||||
|
@ -371,7 +371,7 @@ static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code,
|
||||
alt->com13 = OV9640_COM13_RGB_AVG;
|
||||
alt->com15 = OV9640_COM15_RGB_565;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup registers according to resolution and color encoding */
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/v4l2-dv-timings.h>
|
||||
|
||||
#include <media/v4l2-dv-timings.h>
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/v4l2-dv-timings.h>
|
||||
#include <media/tvp7002.h>
|
||||
#include <media/v4l2-async.h>
|
||||
|
@ -319,7 +319,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
|
||||
|
||||
err_pci_iounmap:
|
||||
pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
|
||||
pci_set_drvdata(fc_pci->pdev, NULL);
|
||||
err_pci_release_regions:
|
||||
pci_release_regions(fc_pci->pdev);
|
||||
err_pci_disable_device:
|
||||
@ -332,7 +331,6 @@ static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
|
||||
if (fc_pci->init_state & FC_PCI_INIT) {
|
||||
free_irq(fc_pci->pdev->irq, fc_pci);
|
||||
pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
|
||||
pci_set_drvdata(fc_pci->pdev, NULL);
|
||||
pci_release_regions(fc_pci->pdev);
|
||||
pci_disable_device(fc_pci->pdev);
|
||||
}
|
||||
|
@ -488,8 +488,7 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
|
||||
btwrite(0, BT848_INT_MASK);
|
||||
|
||||
result = request_irq(bt->irq, bt878_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, "bt878",
|
||||
(void *) bt);
|
||||
IRQF_SHARED, "bt878", (void *) bt);
|
||||
if (result == -EINVAL) {
|
||||
printk(KERN_ERR "bt878(%d): Bad irq number or handler\n",
|
||||
bt878_num);
|
||||
@ -563,7 +562,6 @@ static void bt878_remove(struct pci_dev *pci_dev)
|
||||
bt->shutdown = 1;
|
||||
bt878_mem_free(bt);
|
||||
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
pci_disable_device(pci_dev);
|
||||
return;
|
||||
}
|
||||
|
@ -4086,7 +4086,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
|
||||
/* disable irqs, register irq handler */
|
||||
btwrite(0, BT848_INT_MASK);
|
||||
result = request_irq(btv->c.pci->irq, bttv_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
|
||||
IRQF_SHARED, btv->c.v4l2_dev.name, (void *)btv);
|
||||
if (result < 0) {
|
||||
pr_err("%d: can't get IRQ %d\n",
|
||||
bttv_num, btv->c.pci->irq);
|
||||
|
@ -1031,8 +1031,7 @@ static int cx18_probe(struct pci_dev *pci_dev,
|
||||
|
||||
/* Register IRQ */
|
||||
retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
|
||||
IRQF_SHARED | IRQF_DISABLED,
|
||||
cx->v4l2_dev.name, (void *)cx);
|
||||
IRQF_SHARED, cx->v4l2_dev.name, (void *)cx);
|
||||
if (retval) {
|
||||
CX18_ERR("Failed to register irq %d\n", retval);
|
||||
goto free_i2c;
|
||||
|
@ -23,6 +23,7 @@ config VIDEO_CX23885
|
||||
select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_CX24117 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
|
||||
|
@ -223,6 +223,39 @@ struct cx23885_board cx23885_boards[] = {
|
||||
.name = "Leadtek Winfast PxDVR3200 H",
|
||||
.portc = CX23885_MPEG_DVB,
|
||||
},
|
||||
[CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200] = {
|
||||
.name = "Leadtek Winfast PxPVR2200",
|
||||
.porta = CX23885_ANALOG_VIDEO,
|
||||
.tuner_type = TUNER_XC2028,
|
||||
.tuner_addr = 0x61,
|
||||
.tuner_bus = 1,
|
||||
.input = {{
|
||||
.type = CX23885_VMUX_TELEVISION,
|
||||
.vmux = CX25840_VIN2_CH1 |
|
||||
CX25840_VIN5_CH2,
|
||||
.amux = CX25840_AUDIO8,
|
||||
.gpio0 = 0x704040,
|
||||
}, {
|
||||
.type = CX23885_VMUX_COMPOSITE1,
|
||||
.vmux = CX25840_COMPOSITE1,
|
||||
.amux = CX25840_AUDIO7,
|
||||
.gpio0 = 0x704040,
|
||||
}, {
|
||||
.type = CX23885_VMUX_SVIDEO,
|
||||
.vmux = CX25840_SVIDEO_LUMA3 |
|
||||
CX25840_SVIDEO_CHROMA4,
|
||||
.amux = CX25840_AUDIO7,
|
||||
.gpio0 = 0x704040,
|
||||
}, {
|
||||
.type = CX23885_VMUX_COMPONENT,
|
||||
.vmux = CX25840_VIN7_CH1 |
|
||||
CX25840_VIN6_CH2 |
|
||||
CX25840_VIN8_CH3 |
|
||||
CX25840_COMPONENT_ON,
|
||||
.amux = CX25840_AUDIO7,
|
||||
.gpio0 = 0x704040,
|
||||
} },
|
||||
},
|
||||
[CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
|
||||
.name = "Leadtek Winfast PxDVR3200 H XC4000",
|
||||
.porta = CX23885_ANALOG_VIDEO,
|
||||
@ -259,6 +292,16 @@ struct cx23885_board cx23885_boards[] = {
|
||||
.name = "TurboSight TBS 6920",
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
},
|
||||
[CX23885_BOARD_TBS_6980] = {
|
||||
.name = "TurboSight TBS 6980",
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
.portc = CX23885_MPEG_DVB,
|
||||
},
|
||||
[CX23885_BOARD_TBS_6981] = {
|
||||
.name = "TurboSight TBS 6981",
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
.portc = CX23885_MPEG_DVB,
|
||||
},
|
||||
[CX23885_BOARD_TEVII_S470] = {
|
||||
.name = "TeVii S470",
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
@ -686,6 +729,10 @@ struct cx23885_subid cx23885_subids[] = {
|
||||
.subvendor = 0x107d,
|
||||
.subdevice = 0x6681,
|
||||
.card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
|
||||
}, {
|
||||
.subvendor = 0x107d,
|
||||
.subdevice = 0x6f21,
|
||||
.card = CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200,
|
||||
}, {
|
||||
.subvendor = 0x107d,
|
||||
.subdevice = 0x6f39,
|
||||
@ -698,6 +745,14 @@ struct cx23885_subid cx23885_subids[] = {
|
||||
.subvendor = 0x6920,
|
||||
.subdevice = 0x8888,
|
||||
.card = CX23885_BOARD_TBS_6920,
|
||||
}, {
|
||||
.subvendor = 0x6980,
|
||||
.subdevice = 0x8888,
|
||||
.card = CX23885_BOARD_TBS_6980,
|
||||
}, {
|
||||
.subvendor = 0x6981,
|
||||
.subdevice = 0x8888,
|
||||
.card = CX23885_BOARD_TBS_6981,
|
||||
}, {
|
||||
.subvendor = 0xd470,
|
||||
.subdevice = 0x9022,
|
||||
@ -1023,6 +1078,35 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
|
||||
dev->name, tv.model);
|
||||
}
|
||||
|
||||
/* Some TBS cards require initing a chip using a bitbanged SPI attached
|
||||
to the cx23885 gpio's. If this chip doesn't get init'ed the demod
|
||||
doesn't respond to any command. */
|
||||
static void tbs_card_init(struct cx23885_dev *dev)
|
||||
{
|
||||
int i;
|
||||
const u8 buf[] = {
|
||||
0xe0, 0x06, 0x66, 0x33, 0x65,
|
||||
0x01, 0x17, 0x06, 0xde};
|
||||
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
cx_set(GP0_IO, 0x00070007);
|
||||
usleep_range(1000, 10000);
|
||||
cx_clear(GP0_IO, 2);
|
||||
usleep_range(1000, 10000);
|
||||
for (i = 0; i < 9 * 8; i++) {
|
||||
cx_clear(GP0_IO, 7);
|
||||
usleep_range(1000, 10000);
|
||||
cx_set(GP0_IO,
|
||||
((buf[i >> 3] >> (7 - (i & 7))) & 1) | 4);
|
||||
usleep_range(1000, 10000);
|
||||
}
|
||||
cx_set(GP0_IO, 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int cx23885_tuner_callback(void *priv, int component, int command, int arg)
|
||||
{
|
||||
struct cx23885_tsport *port = priv;
|
||||
@ -1043,6 +1127,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1500:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
|
||||
@ -1208,6 +1293,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
||||
cx_set(GP0_IO, 0x000f000f);
|
||||
break;
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
|
||||
@ -1225,6 +1311,8 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
||||
cx_set(GP0_IO, 0x00040004);
|
||||
break;
|
||||
case CX23885_BOARD_TBS_6920:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
case CX23885_BOARD_PROF_8000:
|
||||
cx_write(MC417_CTL, 0x00000036);
|
||||
cx_write(MC417_OEN, 0x00001000);
|
||||
@ -1473,6 +1561,8 @@ int cx23885_ir_init(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
if (!enable_885_ir)
|
||||
break;
|
||||
dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
|
||||
@ -1516,6 +1606,8 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
|
||||
/* sd_ir is a duplicate pointer to the AV Core, just clear it */
|
||||
dev->sd_ir = NULL;
|
||||
@ -1561,6 +1653,8 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
if (dev->sd_ir)
|
||||
cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
|
||||
break;
|
||||
@ -1676,6 +1770,16 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
break;
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
|
||||
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
|
||||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
tbs_card_init(dev);
|
||||
break;
|
||||
case CX23885_BOARD_MYGICA_X8506:
|
||||
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
@ -1704,6 +1808,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1700:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1400:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1270:
|
||||
@ -1733,6 +1838,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1700:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
|
||||
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
|
||||
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
|
||||
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
|
||||
@ -1752,6 +1858,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
|
||||
case CX23885_BOARD_AVERMEDIA_HC81R:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
|
||||
&dev->i2c_bus[2].i2c_adap,
|
||||
"cx25840", 0x88 >> 1, NULL);
|
||||
|
@ -2129,7 +2129,7 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
|
||||
}
|
||||
|
||||
err = request_irq(pci_dev->irq, cx23885_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "%s: can't get IRQ %d\n",
|
||||
dev->name, pci_dev->irq);
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "stv6110.h"
|
||||
#include "lnbh24.h"
|
||||
#include "cx24116.h"
|
||||
#include "cx24117.h"
|
||||
#include "cimax2.h"
|
||||
#include "lgs8gxx.h"
|
||||
#include "netup-eeprom.h"
|
||||
@ -461,6 +462,10 @@ static struct cx24116_config tbs_cx24116_config = {
|
||||
.demod_address = 0x55,
|
||||
};
|
||||
|
||||
static struct cx24117_config tbs_cx24117_config = {
|
||||
.demod_address = 0x55,
|
||||
};
|
||||
|
||||
static struct ds3000_config tevii_ds3000_config = {
|
||||
.demod_address = 0x68,
|
||||
};
|
||||
@ -1044,6 +1049,25 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
|
||||
|
||||
break;
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
i2c_bus = &dev->i2c_bus[1];
|
||||
|
||||
switch (port->nr) {
|
||||
/* PORT B */
|
||||
case 1:
|
||||
fe0->dvb.frontend = dvb_attach(cx24117_attach,
|
||||
&tbs_cx24117_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
break;
|
||||
/* PORT C */
|
||||
case 2:
|
||||
fe0->dvb.frontend = dvb_attach(cx24117_attach,
|
||||
&tbs_cx24117_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
i2c_bus = &dev->i2c_bus[1];
|
||||
|
||||
|
@ -90,6 +90,8 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
/*
|
||||
* The only boards we handle right now. However other boards
|
||||
* using the CX2388x integrated IR controller should be similar
|
||||
@ -168,6 +170,8 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
|
||||
break;
|
||||
case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
|
||||
case CX23885_BOARD_TEVII_S470:
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
/*
|
||||
* The IR controller on this board only returns pulse widths.
|
||||
* Any other mode setting will fail to set up the device.
|
||||
@ -298,6 +302,14 @@ int cx23885_input_init(struct cx23885_dev *dev)
|
||||
/* A guess at the remote */
|
||||
rc_map = RC_MAP_TOTAL_MEDIA_IN_HAND_02;
|
||||
break;
|
||||
case CX23885_BOARD_TBS_6980:
|
||||
case CX23885_BOARD_TBS_6981:
|
||||
/* Integrated CX23885 IR controller */
|
||||
driver_type = RC_DRIVER_IR_RAW;
|
||||
allowed_protos = RC_BIT_ALL;
|
||||
/* A guess at the remote */
|
||||
rc_map = RC_MAP_TBS_NEC;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -1865,7 +1865,8 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
|
||||
v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
|
||||
|
||||
if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) {
|
||||
if ((dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) ||
|
||||
(dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200)) {
|
||||
struct xc2028_ctrl ctrl = {
|
||||
.fname = XC2028_DEFAULT_FIRMWARE,
|
||||
.max_len = 64
|
||||
|
@ -93,6 +93,9 @@
|
||||
#define CX23885_BOARD_PROF_8000 37
|
||||
#define CX23885_BOARD_HAUPPAUGE_HVR4400 38
|
||||
#define CX23885_BOARD_AVERMEDIA_HC81R 39
|
||||
#define CX23885_BOARD_TBS_6981 40
|
||||
#define CX23885_BOARD_TBS_6980 41
|
||||
#define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
|
||||
|
||||
#define GPIO_0 0x00000001
|
||||
#define GPIO_1 0x00000002
|
||||
|
@ -45,5 +45,3 @@ struct cx25821_board cx25821_boards[] = {
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
|
||||
|
@ -438,7 +438,7 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width,
|
||||
decoder_count = decoder_select + 1;
|
||||
} else {
|
||||
decoder = 0;
|
||||
decoder_count = _num_decoders;
|
||||
decoder_count = dev->_max_num_decoders;
|
||||
}
|
||||
|
||||
switch (width) {
|
||||
@ -506,8 +506,6 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
|
||||
break;
|
||||
}
|
||||
|
||||
_display_field_cnt[decoder] = duration;
|
||||
|
||||
/* update hardware */
|
||||
fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
|
||||
|
||||
@ -667,8 +665,6 @@ int medusa_video_init(struct cx25821_dev *dev)
|
||||
int ret_val = 0;
|
||||
int i = 0;
|
||||
|
||||
_num_decoders = dev->_max_num_decoders;
|
||||
|
||||
/* disable Auto source selection on all video decoders */
|
||||
value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
|
||||
value &= 0xFFFFF0FF;
|
||||
@ -685,8 +681,14 @@ int medusa_video_init(struct cx25821_dev *dev)
|
||||
if (ret_val < 0)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < _num_decoders; i++)
|
||||
medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
|
||||
/*
|
||||
* FIXME: due to a coding bug the duration was always 0. It's
|
||||
* likely that it really should be something else, but due to the
|
||||
* lack of documentation I have no idea what it should be. For
|
||||
* now just fill in 0 as the duration.
|
||||
*/
|
||||
for (i = 0; i < dev->_max_num_decoders; i++)
|
||||
medusa_set_decoderduration(dev, i, 0);
|
||||
|
||||
/* Select monitor as DENC A input, power up the DAC */
|
||||
value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
|
||||
@ -717,7 +719,7 @@ int medusa_video_init(struct cx25821_dev *dev)
|
||||
/* Turn on all of the data out and control output pins. */
|
||||
value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
|
||||
value &= 0xFEF0FE00;
|
||||
if (_num_decoders == MAX_DECODERS) {
|
||||
if (dev->_max_num_decoders == MAX_DECODERS) {
|
||||
/*
|
||||
* Note: The octal board does not support control pins(bit16-19)
|
||||
* These bits are ignored in the octal board.
|
||||
|
@ -40,10 +40,4 @@
|
||||
#define CONTRAST_DEFAULT 5000
|
||||
#define HUE_DEFAULT 5000
|
||||
|
||||
unsigned short _num_decoders;
|
||||
unsigned short _num_cameras;
|
||||
|
||||
unsigned int _video_standard;
|
||||
int _display_field_cnt[MAX_DECODERS];
|
||||
|
||||
#endif
|
||||
|
@ -159,10 +159,10 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_channel *chan, __le32
|
||||
* For the upstream video channel, the risc engine will enable
|
||||
* the FIFO. */
|
||||
if (fifo_enable && line == 3) {
|
||||
*(rp++) = RISC_WRITECR;
|
||||
*(rp++) = sram_ch->dma_ctl;
|
||||
*(rp++) = FLD_VID_FIFO_EN;
|
||||
*(rp++) = 0x00000001;
|
||||
*(rp++) = cpu_to_le32(RISC_WRITECR);
|
||||
*(rp++) = cpu_to_le32(sram_ch->dma_ctl);
|
||||
*(rp++) = cpu_to_le32(FLD_VID_FIFO_EN);
|
||||
*(rp++) = cpu_to_le32(0x00000001);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -834,7 +834,7 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
|
||||
|
||||
/* get irq */
|
||||
err = request_irq(chip->pci->irq, cx8801_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip);
|
||||
IRQF_SHARED, chip->core->name, chip);
|
||||
if (err < 0) {
|
||||
dprintk(0, "%s: can't get IRQ %d\n",
|
||||
chip->core->name, chip->pci->irq);
|
||||
@ -935,8 +935,6 @@ static void cx88_audio_finidev(struct pci_dev *pci)
|
||||
|
||||
snd_card_free((void *)card);
|
||||
|
||||
pci_set_drvdata(pci, NULL);
|
||||
|
||||
devno--;
|
||||
}
|
||||
|
||||
@ -951,27 +949,4 @@ static struct pci_driver cx88_audio_pci_driver = {
|
||||
.remove = cx88_audio_finidev,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
LINUX MODULE INIT
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* module init
|
||||
*/
|
||||
static int __init cx88_audio_init(void)
|
||||
{
|
||||
printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
|
||||
CX88_VERSION);
|
||||
return pci_register_driver(&cx88_audio_pci_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
* module remove
|
||||
*/
|
||||
static void __exit cx88_audio_fini(void)
|
||||
{
|
||||
pci_unregister_driver(&cx88_audio_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cx88_audio_init);
|
||||
module_exit(cx88_audio_fini);
|
||||
module_pci_driver(cx88_audio_pci_driver);
|
||||
|
@ -499,7 +499,7 @@ static int cx8802_init_common(struct cx8802_dev *dev)
|
||||
|
||||
/* get irq */
|
||||
err = request_irq(dev->pci->irq, cx8802_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
|
||||
IRQF_SHARED, dev->core->name, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "%s: can't get IRQ %d\n",
|
||||
dev->core->name, dev->pci->irq);
|
||||
@ -520,7 +520,6 @@ static void cx8802_fini_common(struct cx8802_dev *dev)
|
||||
|
||||
/* unregister stuff */
|
||||
free_irq(dev->pci->irq, dev);
|
||||
pci_set_drvdata(dev->pci, NULL);
|
||||
|
||||
/* free memory */
|
||||
btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
|
||||
@ -903,20 +902,8 @@ static struct pci_driver cx8802_pci_driver = {
|
||||
.remove = cx8802_remove,
|
||||
};
|
||||
|
||||
static int __init cx8802_init(void)
|
||||
{
|
||||
printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
|
||||
CX88_VERSION);
|
||||
return pci_register_driver(&cx8802_pci_driver);
|
||||
}
|
||||
module_pci_driver(cx8802_pci_driver);
|
||||
|
||||
static void __exit cx8802_fini(void)
|
||||
{
|
||||
pci_unregister_driver(&cx8802_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cx8802_init);
|
||||
module_exit(cx8802_fini);
|
||||
EXPORT_SYMBOL(cx8802_buf_prepare);
|
||||
EXPORT_SYMBOL(cx8802_buf_queue);
|
||||
EXPORT_SYMBOL(cx8802_cancel_buffers);
|
||||
|
@ -1738,7 +1738,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
|
||||
|
||||
/* get irq */
|
||||
err = request_irq(pci_dev->irq, cx8800_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, core->name, dev);
|
||||
IRQF_SHARED, core->name, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "%s/0: can't get IRQ %d\n",
|
||||
core->name,pci_dev->irq);
|
||||
@ -1922,7 +1922,6 @@ static void cx8800_finidev(struct pci_dev *pci_dev)
|
||||
|
||||
free_irq(pci_dev->irq, dev);
|
||||
cx8800_unregister_video(dev);
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
|
||||
/* free memory */
|
||||
btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
|
||||
@ -2039,17 +2038,4 @@ static struct pci_driver cx8800_pci_driver = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init cx8800_init(void)
|
||||
{
|
||||
printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
|
||||
CX88_VERSION);
|
||||
return pci_register_driver(&cx8800_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit cx8800_fini(void)
|
||||
{
|
||||
pci_unregister_driver(&cx8800_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cx8800_init);
|
||||
module_exit(cx8800_fini);
|
||||
module_pci_driver(cx8800_pci_driver);
|
||||
|
@ -1544,7 +1544,7 @@ static void ddb_unmap(struct ddb *dev)
|
||||
|
||||
static void ddb_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
|
||||
struct ddb *dev = pci_get_drvdata(pdev);
|
||||
|
||||
ddb_ports_detach(dev);
|
||||
ddb_i2c_release(dev);
|
||||
|
@ -1178,7 +1178,6 @@ err_pci_release_regions:
|
||||
err_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
err_kfree:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(dev);
|
||||
return ret;
|
||||
}
|
||||
@ -1202,8 +1201,7 @@ static void dm1105_remove(struct pci_dev *pdev)
|
||||
dvb_dmxdev_release(&dev->dmxdev);
|
||||
dvb_dmx_release(dvbdemux);
|
||||
dvb_unregister_adapter(dvb_adapter);
|
||||
if (&dev->i2c_adap)
|
||||
i2c_del_adapter(&dev->i2c_adap);
|
||||
i2c_del_adapter(&dev->i2c_adap);
|
||||
|
||||
dm1105_hw_exit(dev);
|
||||
synchronize_irq(pdev->irq);
|
||||
@ -1211,7 +1209,6 @@ static void dm1105_remove(struct pci_dev *pdev)
|
||||
pci_iounmap(pdev, dev->io_mem);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
dm1105_devcount--;
|
||||
kfree(dev);
|
||||
}
|
||||
|
@ -1261,7 +1261,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
|
||||
|
||||
/* Register IRQ */
|
||||
retval = request_irq(itv->pdev->irq, ivtv_irq_handler,
|
||||
IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv);
|
||||
IRQF_SHARED, itv->v4l2_dev.name, (void *)itv);
|
||||
if (retval) {
|
||||
IVTV_ERR("Failed to register irq %d\n", retval);
|
||||
goto free_i2c;
|
||||
|
@ -143,7 +143,6 @@ fail1:
|
||||
|
||||
fail0:
|
||||
dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mantis_pci_init);
|
||||
@ -161,7 +160,6 @@ void mantis_pci_exit(struct mantis_pci *mantis)
|
||||
}
|
||||
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mantis_pci_exit);
|
||||
|
||||
|
@ -1698,7 +1698,7 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
||||
|
||||
meye.mchip_irq = pcidev->irq;
|
||||
if (request_irq(meye.mchip_irq, meye_irq,
|
||||
IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) {
|
||||
IRQF_SHARED, "meye", meye_irq)) {
|
||||
v4l2_err(v4l2_dev, "request_irq failed\n");
|
||||
goto outreqirq;
|
||||
}
|
||||
|
@ -1622,7 +1622,7 @@ static void ngene_unlink(struct ngene *dev)
|
||||
|
||||
void ngene_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev);
|
||||
struct ngene *dev = pci_get_drvdata(pdev);
|
||||
|
||||
if (!dev || !shutdown_workaround)
|
||||
return;
|
||||
@ -1648,7 +1648,6 @@ void ngene_remove(struct pci_dev *pdev)
|
||||
cxd_detach(dev);
|
||||
ngene_stop(dev);
|
||||
ngene_release_buffers(dev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
@ -1702,6 +1701,5 @@ fail1:
|
||||
ngene_release_buffers(dev);
|
||||
fail0:
|
||||
pci_disable_device(pci_dev);
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
return stat;
|
||||
}
|
||||
|
@ -736,7 +736,6 @@ err_pci_release_regions:
|
||||
err_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
err_kfree:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(pluto);
|
||||
goto out;
|
||||
}
|
||||
@ -765,7 +764,6 @@ static void pluto2_remove(struct pci_dev *pdev)
|
||||
pci_iounmap(pdev, pluto->io_mem);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(pluto);
|
||||
}
|
||||
|
||||
|
@ -1076,7 +1076,6 @@ static void pt1_remove(struct pci_dev *pdev)
|
||||
pt1_update_power(pt1);
|
||||
pt1_cleanup_adapters(pt1);
|
||||
i2c_del_adapter(&pt1->i2c_adap);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(pt1);
|
||||
pci_iounmap(pdev, regs);
|
||||
pci_release_regions(pdev);
|
||||
@ -1198,7 +1197,6 @@ err_i2c_del_adapter:
|
||||
err_pt1_cleanup_adapters:
|
||||
pt1_cleanup_adapters(pt1);
|
||||
err_kfree:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(pt1);
|
||||
err_pci_iounmap:
|
||||
pci_iounmap(pdev, regs);
|
||||
|
@ -1096,7 +1096,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
|
||||
|
||||
|
||||
err = request_irq(dev->pci->irq, saa7134_alsa_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->name,
|
||||
IRQF_SHARED, dev->name,
|
||||
(void*) &dev->dmasound);
|
||||
|
||||
if (err < 0) {
|
||||
|
@ -992,7 +992,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
|
||||
|
||||
/* get irq */
|
||||
err = request_irq(pci_dev->irq, saa7134_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "%s: can't get IRQ %d\n",
|
||||
dev->name,pci_dev->irq);
|
||||
|
@ -1232,7 +1232,7 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
|
||||
}
|
||||
|
||||
err = request_irq(pci_dev->irq, saa7164_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
|
||||
pci_dev->irq);
|
||||
@ -1439,7 +1439,6 @@ static void saa7164_finidev(struct pci_dev *pci_dev)
|
||||
|
||||
/* unregister stuff */
|
||||
free_irq(pci_dev->irq, dev);
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
|
||||
mutex_lock(&devlist);
|
||||
list_del(&dev->devlist);
|
||||
|
@ -1293,7 +1293,7 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
|
||||
result = request_irq(zr->pci_dev->irq, zoran_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr);
|
||||
IRQF_SHARED, ZR_DEVNAME(zr), zr);
|
||||
if (result < 0) {
|
||||
if (result == -EINVAL) {
|
||||
dprintk(1,
|
||||
|
@ -143,6 +143,7 @@ if V4L_MEM2MEM_DRIVERS
|
||||
config VIDEO_CODA
|
||||
tristate "Chips&Media Coda multi-standard codec IP"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_MXC
|
||||
select SRAM
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select V4L2_MEM2MEM_DEV
|
||||
---help---
|
||||
@ -212,7 +213,7 @@ config VIDEO_SH_VEU
|
||||
|
||||
config VIDEO_RENESAS_VSP1
|
||||
tristate "Renesas VSP1 Video Processing Engine"
|
||||
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
---help---
|
||||
This is a V4L2 driver for the Renesas VSP1 video processing engine.
|
||||
@ -220,6 +221,22 @@ config VIDEO_RENESAS_VSP1
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called vsp1.
|
||||
|
||||
config VIDEO_TI_VPE
|
||||
tristate "TI VPE (Video Processing Engine) driver"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && SOC_DRA7XX
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select V4L2_MEM2MEM_DEV
|
||||
default n
|
||||
---help---
|
||||
Support for the TI VPE(Video Processing Engine) block
|
||||
found on DRA7XX SoC.
|
||||
|
||||
config VIDEO_TI_VPE_DEBUG
|
||||
bool "VPE debug messages"
|
||||
depends on VIDEO_TI_VPE
|
||||
---help---
|
||||
Enable debug messages on VPE driver.
|
||||
|
||||
endif # V4L_MEM2MEM_DRIVERS
|
||||
|
||||
menuconfig V4L_TEST_DRIVERS
|
||||
|
@ -22,6 +22,8 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe/
|
||||
|
||||
obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
|
||||
obj-$(CONFIG_VIDEO_CODA) += coda.o
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#define CODA_NAME "coda"
|
||||
|
||||
#define CODA_MAX_INSTANCES 4
|
||||
#define CODADX6_MAX_INSTANCES 4
|
||||
|
||||
#define CODA_FMO_BUF_SIZE 32
|
||||
#define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
|
||||
@ -54,8 +54,6 @@
|
||||
|
||||
#define CODA_MAX_FRAMEBUFFERS 8
|
||||
|
||||
#define MAX_W 8192
|
||||
#define MAX_H 8192
|
||||
#define CODA_MAX_FRAME_SIZE 0x100000
|
||||
#define FMO_SLICE_SAVE_BUF_SIZE (32)
|
||||
#define CODA_DEFAULT_GAMMA 4096
|
||||
@ -394,14 +392,57 @@ static struct coda_codec *coda_find_codec(struct coda_dev *dev, int src_fourcc,
|
||||
return &codecs[k];
|
||||
}
|
||||
|
||||
static void coda_get_max_dimensions(struct coda_dev *dev,
|
||||
struct coda_codec *codec,
|
||||
int *max_w, int *max_h)
|
||||
{
|
||||
struct coda_codec *codecs = dev->devtype->codecs;
|
||||
int num_codecs = dev->devtype->num_codecs;
|
||||
unsigned int w, h;
|
||||
int k;
|
||||
|
||||
if (codec) {
|
||||
w = codec->max_w;
|
||||
h = codec->max_h;
|
||||
} else {
|
||||
for (k = 0, w = 0, h = 0; k < num_codecs; k++) {
|
||||
w = max(w, codecs[k].max_w);
|
||||
h = max(h, codecs[k].max_h);
|
||||
}
|
||||
}
|
||||
|
||||
if (max_w)
|
||||
*max_w = w;
|
||||
if (max_h)
|
||||
*max_h = h;
|
||||
}
|
||||
|
||||
static char *coda_product_name(int product)
|
||||
{
|
||||
static char buf[9];
|
||||
|
||||
switch (product) {
|
||||
case CODA_DX6:
|
||||
return "CodaDx6";
|
||||
case CODA_7541:
|
||||
return "CODA7541";
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "(0x%04x)", product);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* V4L2 ioctl() operations.
|
||||
*/
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *cap)
|
||||
static int coda_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *cap)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver));
|
||||
strlcpy(cap->card, CODA_NAME, sizeof(cap->card));
|
||||
strlcpy(cap->card, coda_product_name(ctx->dev->devtype->product),
|
||||
sizeof(cap->card));
|
||||
strlcpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info));
|
||||
/*
|
||||
* This is only a mem-to-mem video device. The capture and output
|
||||
@ -457,6 +498,8 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
|
||||
fmt = &formats[i];
|
||||
strlcpy(f->description, fmt->name, sizeof(f->description));
|
||||
f->pixelformat = fmt->fourcc;
|
||||
if (!coda_format_is_yuv(fmt->fourcc))
|
||||
f->flags |= V4L2_FMT_FLAG_COMPRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -464,8 +507,8 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
static int coda_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
struct vb2_queue *src_vq;
|
||||
@ -483,13 +526,14 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0);
|
||||
}
|
||||
|
||||
static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
static int coda_enum_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
{
|
||||
return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0);
|
||||
}
|
||||
|
||||
static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
||||
static int coda_g_fmt(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct vb2_queue *vq;
|
||||
struct coda_q_data *q_data;
|
||||
@ -516,8 +560,11 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_try_fmt(struct coda_codec *codec, struct v4l2_format *f)
|
||||
static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct coda_dev *dev = ctx->dev;
|
||||
struct coda_q_data *q_data;
|
||||
unsigned int max_w, max_h;
|
||||
enum v4l2_field field;
|
||||
|
||||
@ -531,32 +578,48 @@ static int vidioc_try_fmt(struct coda_codec *codec, struct v4l2_format *f)
|
||||
* if any of the dimensions is unsupported */
|
||||
f->fmt.pix.field = field;
|
||||
|
||||
if (codec) {
|
||||
max_w = codec->max_w;
|
||||
max_h = codec->max_h;
|
||||
} else {
|
||||
max_w = MAX_W;
|
||||
max_h = MAX_H;
|
||||
}
|
||||
v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w,
|
||||
W_ALIGN, &f->fmt.pix.height,
|
||||
MIN_H, max_h, H_ALIGN, S_ALIGN);
|
||||
coda_get_max_dimensions(dev, codec, &max_w, &max_h);
|
||||
v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, W_ALIGN,
|
||||
&f->fmt.pix.height, MIN_H, max_h, H_ALIGN,
|
||||
S_ALIGN);
|
||||
|
||||
if (coda_format_is_yuv(f->fmt.pix.pixelformat)) {
|
||||
switch (f->fmt.pix.pixelformat) {
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
case V4L2_PIX_FMT_YVU420:
|
||||
case V4L2_PIX_FMT_H264:
|
||||
case V4L2_PIX_FMT_MPEG4:
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
break;
|
||||
default:
|
||||
q_data = get_q_data(ctx, f->type);
|
||||
f->fmt.pix.pixelformat = q_data->fourcc;
|
||||
}
|
||||
|
||||
switch (f->fmt.pix.pixelformat) {
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
case V4L2_PIX_FMT_YVU420:
|
||||
/* Frame stride must be multiple of 8 */
|
||||
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8);
|
||||
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
|
||||
f->fmt.pix.height * 3 / 2;
|
||||
} else { /*encoded formats h.264/mpeg4 */
|
||||
break;
|
||||
case V4L2_PIX_FMT_H264:
|
||||
case V4L2_PIX_FMT_MPEG4:
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
f->fmt.pix.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = CODA_MAX_FRAME_SIZE;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
f->fmt.pix.priv = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
static int coda_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
struct coda_codec *codec;
|
||||
@ -584,7 +647,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
|
||||
f->fmt.pix.colorspace = ctx->colorspace;
|
||||
|
||||
ret = vidioc_try_fmt(codec, f);
|
||||
ret = coda_try_fmt(ctx, codec, f);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -600,8 +663,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
static int coda_try_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
struct coda_codec *codec;
|
||||
@ -613,10 +676,10 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
|
||||
if (!f->fmt.pix.colorspace)
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
|
||||
|
||||
return vidioc_try_fmt(codec, f);
|
||||
return coda_try_fmt(ctx, codec, f);
|
||||
}
|
||||
|
||||
static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
|
||||
static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
|
||||
{
|
||||
struct coda_q_data *q_data;
|
||||
struct vb2_queue *vq;
|
||||
@ -646,61 +709,62 @@ static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
static int coda_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
int ret;
|
||||
|
||||
ret = vidioc_try_fmt_vid_cap(file, priv, f);
|
||||
ret = coda_try_fmt_vid_cap(file, priv, f);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return vidioc_s_fmt(ctx, f);
|
||||
return coda_s_fmt(ctx, f);
|
||||
}
|
||||
|
||||
static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
static int coda_s_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
int ret;
|
||||
|
||||
ret = vidioc_try_fmt_vid_out(file, priv, f);
|
||||
ret = coda_try_fmt_vid_out(file, priv, f);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vidioc_s_fmt(ctx, f);
|
||||
ret = coda_s_fmt(ctx, f);
|
||||
if (ret)
|
||||
ctx->colorspace = f->fmt.pix.colorspace;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vidioc_reqbufs(struct file *file, void *priv,
|
||||
struct v4l2_requestbuffers *reqbufs)
|
||||
static int coda_reqbufs(struct file *file, void *priv,
|
||||
struct v4l2_requestbuffers *reqbufs)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
|
||||
}
|
||||
|
||||
static int vidioc_querybuf(struct file *file, void *priv,
|
||||
struct v4l2_buffer *buf)
|
||||
static int coda_querybuf(struct file *file, void *priv,
|
||||
struct v4l2_buffer *buf)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
|
||||
}
|
||||
|
||||
static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
|
||||
static int coda_qbuf(struct file *file, void *priv,
|
||||
struct v4l2_buffer *buf)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
|
||||
}
|
||||
|
||||
static int vidioc_expbuf(struct file *file, void *priv,
|
||||
struct v4l2_exportbuffer *eb)
|
||||
static int coda_expbuf(struct file *file, void *priv,
|
||||
struct v4l2_exportbuffer *eb)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
@ -718,7 +782,8 @@ static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx,
|
||||
(buf->sequence == (ctx->qsequence - 1)));
|
||||
}
|
||||
|
||||
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
|
||||
static int coda_dqbuf(struct file *file, void *priv,
|
||||
struct v4l2_buffer *buf)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
int ret;
|
||||
@ -738,24 +803,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vidioc_create_bufs(struct file *file, void *priv,
|
||||
struct v4l2_create_buffers *create)
|
||||
static int coda_create_bufs(struct file *file, void *priv,
|
||||
struct v4l2_create_buffers *create)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
return v4l2_m2m_create_bufs(file, ctx->m2m_ctx, create);
|
||||
}
|
||||
|
||||
static int vidioc_streamon(struct file *file, void *priv,
|
||||
enum v4l2_buf_type type)
|
||||
static int coda_streamon(struct file *file, void *priv,
|
||||
enum v4l2_buf_type type)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
|
||||
return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
|
||||
}
|
||||
|
||||
static int vidioc_streamoff(struct file *file, void *priv,
|
||||
enum v4l2_buf_type type)
|
||||
static int coda_streamoff(struct file *file, void *priv,
|
||||
enum v4l2_buf_type type)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(priv);
|
||||
int ret;
|
||||
@ -772,23 +837,34 @@ static int vidioc_streamoff(struct file *file, void *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vidioc_decoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_decoder_cmd *dc)
|
||||
static int coda_try_decoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_decoder_cmd *dc)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(fh);
|
||||
|
||||
if (dc->cmd != V4L2_DEC_CMD_STOP)
|
||||
return -EINVAL;
|
||||
|
||||
if ((dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK) ||
|
||||
(dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY))
|
||||
if (dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK)
|
||||
return -EINVAL;
|
||||
|
||||
if (dc->stop.pts != 0)
|
||||
if (!(dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) && (dc->stop.pts != 0))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coda_decoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_decoder_cmd *dc)
|
||||
{
|
||||
struct coda_ctx *ctx = fh_to_ctx(fh);
|
||||
int ret;
|
||||
|
||||
ret = coda_try_decoder_cmd(file, fh, dc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Ignore decoder stop command silently in encoder context */
|
||||
if (ctx->inst_type != CODA_INST_DECODER)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
/* Set the strem-end flag on this context */
|
||||
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
|
||||
@ -796,8 +872,8 @@ static int vidioc_decoder_cmd(struct file *file, void *fh,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_subscribe_event(struct v4l2_fh *fh,
|
||||
const struct v4l2_event_subscription *sub)
|
||||
static int coda_subscribe_event(struct v4l2_fh *fh,
|
||||
const struct v4l2_event_subscription *sub)
|
||||
{
|
||||
switch (sub->type) {
|
||||
case V4L2_EVENT_EOS:
|
||||
@ -808,32 +884,33 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh,
|
||||
}
|
||||
|
||||
static const struct v4l2_ioctl_ops coda_ioctl_ops = {
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_querycap = coda_querycap,
|
||||
|
||||
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
|
||||
.vidioc_g_fmt_vid_cap = vidioc_g_fmt,
|
||||
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
|
||||
.vidioc_enum_fmt_vid_cap = coda_enum_fmt_vid_cap,
|
||||
.vidioc_g_fmt_vid_cap = coda_g_fmt,
|
||||
.vidioc_try_fmt_vid_cap = coda_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = coda_s_fmt_vid_cap,
|
||||
|
||||
.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
|
||||
.vidioc_g_fmt_vid_out = vidioc_g_fmt,
|
||||
.vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
|
||||
.vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
|
||||
.vidioc_enum_fmt_vid_out = coda_enum_fmt_vid_out,
|
||||
.vidioc_g_fmt_vid_out = coda_g_fmt,
|
||||
.vidioc_try_fmt_vid_out = coda_try_fmt_vid_out,
|
||||
.vidioc_s_fmt_vid_out = coda_s_fmt_vid_out,
|
||||
|
||||
.vidioc_reqbufs = vidioc_reqbufs,
|
||||
.vidioc_querybuf = vidioc_querybuf,
|
||||
.vidioc_reqbufs = coda_reqbufs,
|
||||
.vidioc_querybuf = coda_querybuf,
|
||||
|
||||
.vidioc_qbuf = vidioc_qbuf,
|
||||
.vidioc_expbuf = vidioc_expbuf,
|
||||
.vidioc_dqbuf = vidioc_dqbuf,
|
||||
.vidioc_create_bufs = vidioc_create_bufs,
|
||||
.vidioc_qbuf = coda_qbuf,
|
||||
.vidioc_expbuf = coda_expbuf,
|
||||
.vidioc_dqbuf = coda_dqbuf,
|
||||
.vidioc_create_bufs = coda_create_bufs,
|
||||
|
||||
.vidioc_streamon = vidioc_streamon,
|
||||
.vidioc_streamoff = vidioc_streamoff,
|
||||
.vidioc_streamon = coda_streamon,
|
||||
.vidioc_streamoff = coda_streamoff,
|
||||
|
||||
.vidioc_decoder_cmd = vidioc_decoder_cmd,
|
||||
.vidioc_try_decoder_cmd = coda_try_decoder_cmd,
|
||||
.vidioc_decoder_cmd = coda_decoder_cmd,
|
||||
|
||||
.vidioc_subscribe_event = vidioc_subscribe_event,
|
||||
.vidioc_subscribe_event = coda_subscribe_event,
|
||||
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||
};
|
||||
|
||||
@ -1928,8 +2005,9 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||
if (!(ctx->streamon_out & ctx->streamon_cap))
|
||||
return 0;
|
||||
|
||||
/* Allow device_run with no buffers queued and after streamoff */
|
||||
v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true);
|
||||
/* Allow decoder device_run with no new buffers queued */
|
||||
if (ctx->inst_type == CODA_INST_DECODER)
|
||||
v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true);
|
||||
|
||||
ctx->gopcounter = ctx->params.gop_size - 1;
|
||||
buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
|
||||
@ -2071,10 +2149,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||
coda_setup_iram(ctx);
|
||||
|
||||
if (dst_fourcc == V4L2_PIX_FMT_H264) {
|
||||
value = (FMO_SLICE_SAVE_BUF_SIZE << 7);
|
||||
value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET;
|
||||
value |= 0 & CODA_FMOPARAM_SLICENUM_MASK;
|
||||
if (dev->devtype->product == CODA_DX6) {
|
||||
value = FMO_SLICE_SAVE_BUF_SIZE << 7;
|
||||
coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
|
||||
} else {
|
||||
coda_write(dev, ctx->iram_info.search_ram_paddr,
|
||||
@ -2371,7 +2447,13 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq,
|
||||
|
||||
static int coda_next_free_instance(struct coda_dev *dev)
|
||||
{
|
||||
return ffz(dev->instance_mask);
|
||||
int idx = ffz(dev->instance_mask);
|
||||
|
||||
if ((idx < 0) ||
|
||||
(dev->devtype->product == CODA_DX6 && idx > CODADX6_MAX_INSTANCES))
|
||||
return -EBUSY;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int coda_open(struct file *file)
|
||||
@ -2386,8 +2468,8 @@ static int coda_open(struct file *file)
|
||||
return -ENOMEM;
|
||||
|
||||
idx = coda_next_free_instance(dev);
|
||||
if (idx >= CODA_MAX_INSTANCES) {
|
||||
ret = -EBUSY;
|
||||
if (idx < 0) {
|
||||
ret = idx;
|
||||
goto err_coda_max;
|
||||
}
|
||||
set_bit(idx, &dev->instance_mask);
|
||||
@ -2719,7 +2801,6 @@ static void coda_finish_encode(struct coda_ctx *ctx)
|
||||
dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
|
||||
|
||||
/* Get results from the coda */
|
||||
coda_read(dev, CODA_RET_ENC_PIC_TYPE);
|
||||
start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
|
||||
wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
|
||||
|
||||
@ -2739,7 +2820,7 @@ static void coda_finish_encode(struct coda_ctx *ctx)
|
||||
coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM);
|
||||
coda_read(dev, CODA_RET_ENC_PIC_FLAG);
|
||||
|
||||
if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
|
||||
if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) {
|
||||
dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
|
||||
dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
|
||||
} else {
|
||||
@ -2861,21 +2942,6 @@ static bool coda_firmware_supported(u32 vernum)
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *coda_product_name(int product)
|
||||
{
|
||||
static char buf[9];
|
||||
|
||||
switch (product) {
|
||||
case CODA_DX6:
|
||||
return "CodaDx6";
|
||||
case CODA_7541:
|
||||
return "CODA7541";
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "(0x%04x)", product);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
static int coda_hw_init(struct coda_dev *dev)
|
||||
{
|
||||
u16 product, major, minor, release;
|
||||
|
@ -1785,7 +1785,7 @@ static int vpbe_display_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
irq = res->start;
|
||||
err = devm_request_irq(&pdev->dev, irq, venc_isr, IRQF_DISABLED,
|
||||
err = devm_request_irq(&pdev->dev, irq, venc_isr, 0,
|
||||
VPBE_DISPLAY_DRIVER, disp_dev);
|
||||
if (err) {
|
||||
v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
|
||||
|
@ -688,7 +688,7 @@ static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
|
||||
frame_format = ccdc_dev->hw_ops.get_frame_format();
|
||||
if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {
|
||||
return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr,
|
||||
IRQF_DISABLED, "vpfe_capture1",
|
||||
0, "vpfe_capture1",
|
||||
vpfe_dev);
|
||||
}
|
||||
return 0;
|
||||
@ -1863,7 +1863,7 @@ static int vpfe_probe(struct platform_device *pdev)
|
||||
}
|
||||
vpfe_dev->ccdc_irq1 = res1->start;
|
||||
|
||||
ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
|
||||
ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, 0,
|
||||
"vpfe_capture0", vpfe_dev);
|
||||
|
||||
if (0 != ret) {
|
||||
|
@ -2154,7 +2154,7 @@ static __init int vpif_probe(struct platform_device *pdev)
|
||||
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
err = -ENOMEM;
|
||||
err = -ENODEV;
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
v4l2_info(&vpif_obj.v4l2_dev,
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define GSC_DST_FMT (1 << 2)
|
||||
#define GSC_CTX_M2M (1 << 3)
|
||||
#define GSC_CTX_STOP_REQ (1 << 6)
|
||||
#define GSC_CTX_ABORT (1 << 7)
|
||||
|
||||
enum gsc_dev_flags {
|
||||
/* for global */
|
||||
|
@ -46,6 +46,17 @@ static int gsc_m2m_ctx_stop_req(struct gsc_ctx *ctx)
|
||||
return ret == 0 ? -ETIMEDOUT : ret;
|
||||
}
|
||||
|
||||
static void __gsc_m2m_job_abort(struct gsc_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gsc_m2m_ctx_stop_req(ctx);
|
||||
if ((ret == -ETIMEDOUT) || (ctx->state & GSC_CTX_ABORT)) {
|
||||
gsc_ctx_state_lock_clear(GSC_CTX_STOP_REQ | GSC_CTX_ABORT, ctx);
|
||||
gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||
{
|
||||
struct gsc_ctx *ctx = q->drv_priv;
|
||||
@ -58,11 +69,8 @@ static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||
static int gsc_m2m_stop_streaming(struct vb2_queue *q)
|
||||
{
|
||||
struct gsc_ctx *ctx = q->drv_priv;
|
||||
int ret;
|
||||
|
||||
ret = gsc_m2m_ctx_stop_req(ctx);
|
||||
if (ret == -ETIMEDOUT)
|
||||
gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
|
||||
__gsc_m2m_job_abort(ctx);
|
||||
|
||||
pm_runtime_put(&ctx->gsc_dev->pdev->dev);
|
||||
|
||||
@ -91,15 +99,9 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void gsc_m2m_job_abort(void *priv)
|
||||
{
|
||||
struct gsc_ctx *ctx = priv;
|
||||
int ret;
|
||||
|
||||
ret = gsc_m2m_ctx_stop_req(ctx);
|
||||
if (ret == -ETIMEDOUT)
|
||||
gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
|
||||
__gsc_m2m_job_abort((struct gsc_ctx *)priv);
|
||||
}
|
||||
|
||||
static int gsc_get_bufs(struct gsc_ctx *ctx)
|
||||
@ -150,9 +152,10 @@ static void gsc_m2m_device_run(void *priv)
|
||||
gsc->m2m.ctx = ctx;
|
||||
}
|
||||
|
||||
is_set = (ctx->state & GSC_CTX_STOP_REQ) ? 1 : 0;
|
||||
ctx->state &= ~GSC_CTX_STOP_REQ;
|
||||
is_set = ctx->state & GSC_CTX_STOP_REQ;
|
||||
if (is_set) {
|
||||
ctx->state &= ~GSC_CTX_STOP_REQ;
|
||||
ctx->state |= GSC_CTX_ABORT;
|
||||
wake_up(&gsc->irq_queue);
|
||||
goto put_device;
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ static int __ctrl_set_metering(struct fimc_is *is, unsigned int value)
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
__is_set_isp_metering(is, IS_METERING_CONFIG_CMD, val);
|
||||
return 0;
|
||||
|
@ -1084,8 +1084,7 @@ free_dev:
|
||||
|
||||
static int deinterlace_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct deinterlace_dev *pcdev =
|
||||
(struct deinterlace_dev *)platform_get_drvdata(pdev);
|
||||
struct deinterlace_dev *pcdev = platform_get_drvdata(pdev);
|
||||
|
||||
v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
|
||||
v4l2_m2m_release(pcdev->m2m_dev);
|
||||
|
@ -1221,16 +1221,16 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
|
||||
{
|
||||
struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
|
||||
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
|
||||
struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
|
||||
struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
|
||||
struct mcam_dma_desc *desc = mvb->dma_desc;
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
mvb->dma_desc_nent = dma_map_sg(cam->dev, sgd->sglist, sgd->num_pages,
|
||||
DMA_FROM_DEVICE);
|
||||
mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl,
|
||||
sg_table->nents, DMA_FROM_DEVICE);
|
||||
if (mvb->dma_desc_nent <= 0)
|
||||
return -EIO; /* Not sure what's right here */
|
||||
for_each_sg(sgd->sglist, sg, mvb->dma_desc_nent, i) {
|
||||
for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) {
|
||||
desc->dma_addr = sg_dma_address(sg);
|
||||
desc->segment_len = sg_dma_len(sg);
|
||||
desc++;
|
||||
@ -1241,9 +1241,11 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
|
||||
static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
|
||||
{
|
||||
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
|
||||
struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
|
||||
struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
|
||||
|
||||
dma_unmap_sg(cam->dev, sgd->sglist, sgd->num_pages, DMA_FROM_DEVICE);
|
||||
if (sg_table)
|
||||
dma_unmap_sg(cam->dev, sg_table->sgl,
|
||||
sg_table->nents, DMA_FROM_DEVICE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -481,7 +481,6 @@ static int mmpcam_remove(struct mmp_camera *cam)
|
||||
struct mmp_camera_platform_data *pdata;
|
||||
|
||||
mmpcam_remove_device(cam);
|
||||
free_irq(cam->irq, mcam);
|
||||
mccic_shutdown(mcam);
|
||||
mmpcam_power_down(mcam);
|
||||
pdata = cam->pdev->dev.platform_data;
|
||||
|
@ -1090,8 +1090,7 @@ unreg_dev:
|
||||
|
||||
static int m2mtest_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct m2mtest_dev *dev =
|
||||
(struct m2mtest_dev *)platform_get_drvdata(pdev);
|
||||
struct m2mtest_dev *dev = platform_get_drvdata(pdev);
|
||||
|
||||
v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
|
||||
v4l2_m2m_release(dev->m2m_dev);
|
||||
|
@ -840,7 +840,7 @@ put_clk:
|
||||
|
||||
static int g2d_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct g2d_dev *dev = (struct g2d_dev *)platform_get_drvdata(pdev);
|
||||
struct g2d_dev *dev = platform_get_drvdata(pdev);
|
||||
|
||||
v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME);
|
||||
v4l2_m2m_release(dev->m2m_dev);
|
||||
|
@ -404,7 +404,11 @@ leave_handle_frame:
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
BUG();
|
||||
s5p_mfc_clock_off();
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
/* if suspending, wake up device and do not try_run again*/
|
||||
if (test_bit(0, &dev->enter_suspend))
|
||||
wake_up_dev(dev, reason, err);
|
||||
else
|
||||
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
|
||||
}
|
||||
|
||||
/* Error handling for interrupt */
|
||||
@ -1101,7 +1105,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
|
||||
}
|
||||
dev->irq = res->start;
|
||||
ret = devm_request_irq(&pdev->dev, dev->irq, s5p_mfc_irq,
|
||||
IRQF_DISABLED, pdev->name, dev);
|
||||
0, pdev->name, dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
|
||||
goto err_res;
|
||||
@ -1286,9 +1290,7 @@ static int s5p_mfc_suspend(struct device *dev)
|
||||
/* Try and lock the HW */
|
||||
/* Wait on the interrupt waitqueue */
|
||||
ret = wait_event_interruptible_timeout(m_dev->queue,
|
||||
m_dev->int_cond || m_dev->ctx[m_dev->curr_ctx]->int_cond,
|
||||
msecs_to_jiffies(MFC_INT_TIMEOUT));
|
||||
|
||||
m_dev->int_cond, msecs_to_jiffies(MFC_INT_TIMEOUT));
|
||||
if (ret == 0) {
|
||||
mfc_err("Waiting for hardware to finish timed out\n");
|
||||
return -EIO;
|
||||
|
@ -111,7 +111,7 @@ static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
|
||||
break;
|
||||
default:
|
||||
h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
|
||||
};
|
||||
}
|
||||
h2r_args.arg[1] = 0; /* no crc & no pixelcache */
|
||||
h2r_args.arg[2] = ctx->ctx.ofs;
|
||||
h2r_args.arg[3] = ctx->ctx.size;
|
||||
|
@ -113,7 +113,7 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
|
||||
break;
|
||||
default:
|
||||
codec_type = S5P_FIMV_CODEC_NONE_V6;
|
||||
};
|
||||
}
|
||||
mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
|
||||
mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
|
||||
mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
|
||||
|
@ -113,7 +113,7 @@ static struct mfc_control controls[] = {
|
||||
.minimum = 0,
|
||||
.maximum = (1 << 16) - 1,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
.default_value = 12,
|
||||
},
|
||||
{
|
||||
.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
|
||||
@ -356,7 +356,7 @@ static struct mfc_control controls[] = {
|
||||
.minimum = 0,
|
||||
.maximum = 51,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
.default_value = 51,
|
||||
},
|
||||
{
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
|
||||
@ -399,7 +399,7 @@ static struct mfc_control controls[] = {
|
||||
.minimum = 1,
|
||||
.maximum = 31,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
.default_value = 31,
|
||||
},
|
||||
{
|
||||
.id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
|
||||
@ -444,7 +444,7 @@ static struct mfc_control controls[] = {
|
||||
.minimum = 0,
|
||||
.maximum = 51,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
.default_value = 51,
|
||||
},
|
||||
{
|
||||
.id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP,
|
||||
|
@ -1582,7 +1582,7 @@ static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
|
||||
break;
|
||||
default:
|
||||
reason = S5P_MFC_R2H_CMD_EMPTY;
|
||||
};
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ static void mxr_graph_fix_geometry(struct mxr_layer *layer,
|
||||
src->width + src->x_offset, 32767);
|
||||
src->full_height = clamp_val(src->full_height,
|
||||
src->height + src->y_offset, 2047);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* PUBLIC API */
|
||||
|
@ -197,7 +197,7 @@ static void mxr_vp_fix_geometry(struct mxr_layer *layer,
|
||||
ALIGN(src->width + src->x_offset, 8), 8192U);
|
||||
src->full_height = clamp(src->full_height,
|
||||
src->height + src->y_offset, 8192U);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* PUBLIC API */
|
||||
|
@ -105,6 +105,7 @@
|
||||
#define VIN_MAX_HEIGHT 2048
|
||||
|
||||
enum chip_id {
|
||||
RCAR_H2,
|
||||
RCAR_H1,
|
||||
RCAR_M1,
|
||||
RCAR_E1,
|
||||
@ -300,7 +301,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
|
||||
dmr = 0;
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB32:
|
||||
if (priv->chip == RCAR_H1 || priv->chip == RCAR_E1) {
|
||||
if (priv->chip == RCAR_H2 || priv->chip == RCAR_H1 ||
|
||||
priv->chip == RCAR_E1) {
|
||||
dmr = VNDMR_EXRGB;
|
||||
break;
|
||||
}
|
||||
@ -1381,6 +1383,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = {
|
||||
};
|
||||
|
||||
static struct platform_device_id rcar_vin_id_table[] = {
|
||||
{ "r8a7790-vin", RCAR_H2 },
|
||||
{ "r8a7779-vin", RCAR_H1 },
|
||||
{ "r8a7778-vin", RCAR_M1 },
|
||||
{ "uPD35004-vin", RCAR_E1 },
|
||||
|
@ -1800,7 +1800,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
|
||||
|
||||
/* request irq */
|
||||
err = devm_request_irq(&pdev->dev, pcdev->irq, sh_mobile_ceu_irq,
|
||||
IRQF_DISABLED, dev_name(&pdev->dev), pcdev);
|
||||
0, dev_name(&pdev->dev), pcdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Unable to register CEU interrupt.\n");
|
||||
goto exit_release_mem;
|
||||
|
@ -71,13 +71,23 @@ static int video_dev_create(struct soc_camera_device *icd);
|
||||
int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd,
|
||||
struct v4l2_clk *clk)
|
||||
{
|
||||
int ret = clk ? v4l2_clk_enable(clk) : 0;
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Cannot enable clock: %d\n", ret);
|
||||
return ret;
|
||||
int ret;
|
||||
bool clock_toggle;
|
||||
|
||||
if (clk && (!ssdd->unbalanced_power ||
|
||||
!test_and_set_bit(0, &ssdd->clock_state))) {
|
||||
ret = v4l2_clk_enable(clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Cannot enable clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
clock_toggle = true;
|
||||
} else {
|
||||
clock_toggle = false;
|
||||
}
|
||||
ret = regulator_bulk_enable(ssdd->num_regulators,
|
||||
ssdd->regulators);
|
||||
|
||||
ret = regulator_bulk_enable(ssdd->sd_pdata.num_regulators,
|
||||
ssdd->sd_pdata.regulators);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Cannot enable regulators\n");
|
||||
goto eregenable;
|
||||
@ -95,10 +105,10 @@ int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd,
|
||||
return 0;
|
||||
|
||||
epwron:
|
||||
regulator_bulk_disable(ssdd->num_regulators,
|
||||
ssdd->regulators);
|
||||
regulator_bulk_disable(ssdd->sd_pdata.num_regulators,
|
||||
ssdd->sd_pdata.regulators);
|
||||
eregenable:
|
||||
if (clk)
|
||||
if (clock_toggle)
|
||||
v4l2_clk_disable(clk);
|
||||
|
||||
return ret;
|
||||
@ -120,14 +130,14 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd
|
||||
}
|
||||
}
|
||||
|
||||
err = regulator_bulk_disable(ssdd->num_regulators,
|
||||
ssdd->regulators);
|
||||
err = regulator_bulk_disable(ssdd->sd_pdata.num_regulators,
|
||||
ssdd->sd_pdata.regulators);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "Cannot disable regulators\n");
|
||||
ret = ret ? : err;
|
||||
}
|
||||
|
||||
if (clk)
|
||||
if (clk && (!ssdd->unbalanced_power || test_and_clear_bit(0, &ssdd->clock_state)))
|
||||
v4l2_clk_disable(clk);
|
||||
|
||||
return ret;
|
||||
@ -137,8 +147,8 @@ EXPORT_SYMBOL(soc_camera_power_off);
|
||||
int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd)
|
||||
{
|
||||
/* Should not have any effect in synchronous case */
|
||||
return devm_regulator_bulk_get(dev, ssdd->num_regulators,
|
||||
ssdd->regulators);
|
||||
return devm_regulator_bulk_get(dev, ssdd->sd_pdata.num_regulators,
|
||||
ssdd->sd_pdata.regulators);
|
||||
}
|
||||
EXPORT_SYMBOL(soc_camera_power_init);
|
||||
|
||||
@ -1346,8 +1356,8 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd,
|
||||
* soc_camera_pdrv_probe(), make sure the subdevice driver doesn't try
|
||||
* to allocate them again.
|
||||
*/
|
||||
ssdd->num_regulators = 0;
|
||||
ssdd->regulators = NULL;
|
||||
ssdd->sd_pdata.num_regulators = 0;
|
||||
ssdd->sd_pdata.regulators = NULL;
|
||||
shd->board_info->platform_data = ssdd;
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "%d-%04x",
|
||||
@ -2020,8 +2030,8 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev)
|
||||
* that case regulators are attached to the I2C device and not to the
|
||||
* camera platform device.
|
||||
*/
|
||||
ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators,
|
||||
ssdd->regulators);
|
||||
ret = devm_regulator_bulk_get(&pdev->dev, ssdd->sd_pdata.num_regulators,
|
||||
ssdd->sd_pdata.regulators);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
5
drivers/media/platform/ti-vpe/Makefile
Normal file
5
drivers/media/platform/ti-vpe/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o
|
||||
|
||||
ti-vpe-y := vpe.o vpdma.o
|
||||
|
||||
ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG
|
846
drivers/media/platform/ti-vpe/vpdma.c
Normal file
846
drivers/media/platform/ti-vpe/vpdma.c
Normal file
@ -0,0 +1,846 @@
|
||||
/*
|
||||
* VPDMA helper library
|
||||
*
|
||||
* Copyright (c) 2013 Texas Instruments Inc.
|
||||
*
|
||||
* David Griego, <dagriego@biglakesoftware.com>
|
||||
* Dale Farnsworth, <dale@farnsworth.org>
|
||||
* Archit Taneja, <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include "vpdma.h"
|
||||
#include "vpdma_priv.h"
|
||||
|
||||
#define VPDMA_FIRMWARE "vpdma-1b8.bin"
|
||||
|
||||
const struct vpdma_data_format vpdma_yuv_fmts[] = {
|
||||
[VPDMA_DATA_FMT_Y444] = {
|
||||
.data_type = DATA_TYPE_Y444,
|
||||
.depth = 8,
|
||||
},
|
||||
[VPDMA_DATA_FMT_Y422] = {
|
||||
.data_type = DATA_TYPE_Y422,
|
||||
.depth = 8,
|
||||
},
|
||||
[VPDMA_DATA_FMT_Y420] = {
|
||||
.data_type = DATA_TYPE_Y420,
|
||||
.depth = 8,
|
||||
},
|
||||
[VPDMA_DATA_FMT_C444] = {
|
||||
.data_type = DATA_TYPE_C444,
|
||||
.depth = 8,
|
||||
},
|
||||
[VPDMA_DATA_FMT_C422] = {
|
||||
.data_type = DATA_TYPE_C422,
|
||||
.depth = 8,
|
||||
},
|
||||
[VPDMA_DATA_FMT_C420] = {
|
||||
.data_type = DATA_TYPE_C420,
|
||||
.depth = 4,
|
||||
},
|
||||
[VPDMA_DATA_FMT_YC422] = {
|
||||
.data_type = DATA_TYPE_YC422,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_YC444] = {
|
||||
.data_type = DATA_TYPE_YC444,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_CY422] = {
|
||||
.data_type = DATA_TYPE_CY422,
|
||||
.depth = 16,
|
||||
},
|
||||
};
|
||||
|
||||
const struct vpdma_data_format vpdma_rgb_fmts[] = {
|
||||
[VPDMA_DATA_FMT_RGB565] = {
|
||||
.data_type = DATA_TYPE_RGB16_565,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ARGB16_1555] = {
|
||||
.data_type = DATA_TYPE_ARGB_1555,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ARGB16] = {
|
||||
.data_type = DATA_TYPE_ARGB_4444,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_RGBA16_5551] = {
|
||||
.data_type = DATA_TYPE_RGBA_5551,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_RGBA16] = {
|
||||
.data_type = DATA_TYPE_RGBA_4444,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ARGB24] = {
|
||||
.data_type = DATA_TYPE_ARGB24_6666,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_RGB24] = {
|
||||
.data_type = DATA_TYPE_RGB24_888,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ARGB32] = {
|
||||
.data_type = DATA_TYPE_ARGB32_8888,
|
||||
.depth = 32,
|
||||
},
|
||||
[VPDMA_DATA_FMT_RGBA24] = {
|
||||
.data_type = DATA_TYPE_RGBA24_6666,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_RGBA32] = {
|
||||
.data_type = DATA_TYPE_RGBA32_8888,
|
||||
.depth = 32,
|
||||
},
|
||||
[VPDMA_DATA_FMT_BGR565] = {
|
||||
.data_type = DATA_TYPE_BGR16_565,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ABGR16_1555] = {
|
||||
.data_type = DATA_TYPE_ABGR_1555,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ABGR16] = {
|
||||
.data_type = DATA_TYPE_ABGR_4444,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_BGRA16_5551] = {
|
||||
.data_type = DATA_TYPE_BGRA_5551,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_BGRA16] = {
|
||||
.data_type = DATA_TYPE_BGRA_4444,
|
||||
.depth = 16,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ABGR24] = {
|
||||
.data_type = DATA_TYPE_ABGR24_6666,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_BGR24] = {
|
||||
.data_type = DATA_TYPE_BGR24_888,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_ABGR32] = {
|
||||
.data_type = DATA_TYPE_ABGR32_8888,
|
||||
.depth = 32,
|
||||
},
|
||||
[VPDMA_DATA_FMT_BGRA24] = {
|
||||
.data_type = DATA_TYPE_BGRA24_6666,
|
||||
.depth = 24,
|
||||
},
|
||||
[VPDMA_DATA_FMT_BGRA32] = {
|
||||
.data_type = DATA_TYPE_BGRA32_8888,
|
||||
.depth = 32,
|
||||
},
|
||||
};
|
||||
|
||||
const struct vpdma_data_format vpdma_misc_fmts[] = {
|
||||
[VPDMA_DATA_FMT_MV] = {
|
||||
.data_type = DATA_TYPE_MV,
|
||||
.depth = 4,
|
||||
},
|
||||
};
|
||||
|
||||
struct vpdma_channel_info {
|
||||
int num; /* VPDMA channel number */
|
||||
int cstat_offset; /* client CSTAT register offset */
|
||||
};
|
||||
|
||||
static const struct vpdma_channel_info chan_info[] = {
|
||||
[VPE_CHAN_LUMA1_IN] = {
|
||||
.num = VPE_CHAN_NUM_LUMA1_IN,
|
||||
.cstat_offset = VPDMA_DEI_LUMA1_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_CHROMA1_IN] = {
|
||||
.num = VPE_CHAN_NUM_CHROMA1_IN,
|
||||
.cstat_offset = VPDMA_DEI_CHROMA1_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_LUMA2_IN] = {
|
||||
.num = VPE_CHAN_NUM_LUMA2_IN,
|
||||
.cstat_offset = VPDMA_DEI_LUMA2_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_CHROMA2_IN] = {
|
||||
.num = VPE_CHAN_NUM_CHROMA2_IN,
|
||||
.cstat_offset = VPDMA_DEI_CHROMA2_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_LUMA3_IN] = {
|
||||
.num = VPE_CHAN_NUM_LUMA3_IN,
|
||||
.cstat_offset = VPDMA_DEI_LUMA3_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_CHROMA3_IN] = {
|
||||
.num = VPE_CHAN_NUM_CHROMA3_IN,
|
||||
.cstat_offset = VPDMA_DEI_CHROMA3_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_MV_IN] = {
|
||||
.num = VPE_CHAN_NUM_MV_IN,
|
||||
.cstat_offset = VPDMA_DEI_MV_IN_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_MV_OUT] = {
|
||||
.num = VPE_CHAN_NUM_MV_OUT,
|
||||
.cstat_offset = VPDMA_DEI_MV_OUT_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_LUMA_OUT] = {
|
||||
.num = VPE_CHAN_NUM_LUMA_OUT,
|
||||
.cstat_offset = VPDMA_VIP_UP_Y_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_CHROMA_OUT] = {
|
||||
.num = VPE_CHAN_NUM_CHROMA_OUT,
|
||||
.cstat_offset = VPDMA_VIP_UP_UV_CSTAT,
|
||||
},
|
||||
[VPE_CHAN_RGB_OUT] = {
|
||||
.num = VPE_CHAN_NUM_RGB_OUT,
|
||||
.cstat_offset = VPDMA_VIP_UP_Y_CSTAT,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 read_reg(struct vpdma_data *vpdma, int offset)
|
||||
{
|
||||
return ioread32(vpdma->base + offset);
|
||||
}
|
||||
|
||||
static void write_reg(struct vpdma_data *vpdma, int offset, u32 value)
|
||||
{
|
||||
iowrite32(value, vpdma->base + offset);
|
||||
}
|
||||
|
||||
static int read_field_reg(struct vpdma_data *vpdma, int offset,
|
||||
u32 mask, int shift)
|
||||
{
|
||||
return (read_reg(vpdma, offset) & (mask << shift)) >> shift;
|
||||
}
|
||||
|
||||
static void write_field_reg(struct vpdma_data *vpdma, int offset, u32 field,
|
||||
u32 mask, int shift)
|
||||
{
|
||||
u32 val = read_reg(vpdma, offset);
|
||||
|
||||
val &= ~(mask << shift);
|
||||
val |= (field & mask) << shift;
|
||||
|
||||
write_reg(vpdma, offset, val);
|
||||
}
|
||||
|
||||
void vpdma_dump_regs(struct vpdma_data *vpdma)
|
||||
{
|
||||
struct device *dev = &vpdma->pdev->dev;
|
||||
|
||||
#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(vpdma, VPDMA_##r))
|
||||
|
||||
dev_dbg(dev, "VPDMA Registers:\n");
|
||||
|
||||
DUMPREG(PID);
|
||||
DUMPREG(LIST_ADDR);
|
||||
DUMPREG(LIST_ATTR);
|
||||
DUMPREG(LIST_STAT_SYNC);
|
||||
DUMPREG(BG_RGB);
|
||||
DUMPREG(BG_YUV);
|
||||
DUMPREG(SETUP);
|
||||
DUMPREG(MAX_SIZE1);
|
||||
DUMPREG(MAX_SIZE2);
|
||||
DUMPREG(MAX_SIZE3);
|
||||
|
||||
/*
|
||||
* dumping registers of only group0 and group3, because VPE channels
|
||||
* lie within group0 and group3 registers
|
||||
*/
|
||||
DUMPREG(INT_CHAN_STAT(0));
|
||||
DUMPREG(INT_CHAN_MASK(0));
|
||||
DUMPREG(INT_CHAN_STAT(3));
|
||||
DUMPREG(INT_CHAN_MASK(3));
|
||||
DUMPREG(INT_CLIENT0_STAT);
|
||||
DUMPREG(INT_CLIENT0_MASK);
|
||||
DUMPREG(INT_CLIENT1_STAT);
|
||||
DUMPREG(INT_CLIENT1_MASK);
|
||||
DUMPREG(INT_LIST0_STAT);
|
||||
DUMPREG(INT_LIST0_MASK);
|
||||
|
||||
/*
|
||||
* these are registers specific to VPE clients, we can make this
|
||||
* function dump client registers specific to VPE or VIP based on
|
||||
* who is using it
|
||||
*/
|
||||
DUMPREG(DEI_CHROMA1_CSTAT);
|
||||
DUMPREG(DEI_LUMA1_CSTAT);
|
||||
DUMPREG(DEI_CHROMA2_CSTAT);
|
||||
DUMPREG(DEI_LUMA2_CSTAT);
|
||||
DUMPREG(DEI_CHROMA3_CSTAT);
|
||||
DUMPREG(DEI_LUMA3_CSTAT);
|
||||
DUMPREG(DEI_MV_IN_CSTAT);
|
||||
DUMPREG(DEI_MV_OUT_CSTAT);
|
||||
DUMPREG(VIP_UP_Y_CSTAT);
|
||||
DUMPREG(VIP_UP_UV_CSTAT);
|
||||
DUMPREG(VPI_CTL_CSTAT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a DMA buffer
|
||||
*/
|
||||
int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size)
|
||||
{
|
||||
buf->size = size;
|
||||
buf->mapped = false;
|
||||
buf->addr = kzalloc(size, GFP_KERNEL);
|
||||
if (!buf->addr)
|
||||
return -ENOMEM;
|
||||
|
||||
WARN_ON((u32) buf->addr & VPDMA_DESC_ALIGN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vpdma_free_desc_buf(struct vpdma_buf *buf)
|
||||
{
|
||||
WARN_ON(buf->mapped);
|
||||
kfree(buf->addr);
|
||||
buf->addr = NULL;
|
||||
buf->size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* map descriptor/payload DMA buffer, enabling DMA access
|
||||
*/
|
||||
int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf)
|
||||
{
|
||||
struct device *dev = &vpdma->pdev->dev;
|
||||
|
||||
WARN_ON(buf->mapped);
|
||||
buf->dma_addr = dma_map_single(dev, buf->addr, buf->size,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, buf->dma_addr)) {
|
||||
dev_err(dev, "failed to map buffer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf->mapped = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* unmap descriptor/payload DMA buffer, disabling DMA access and
|
||||
* allowing the main processor to acces the data
|
||||
*/
|
||||
void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf)
|
||||
{
|
||||
struct device *dev = &vpdma->pdev->dev;
|
||||
|
||||
if (buf->mapped)
|
||||
dma_unmap_single(dev, buf->dma_addr, buf->size, DMA_TO_DEVICE);
|
||||
|
||||
buf->mapped = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a descriptor list, the user of this list will append configuration,
|
||||
* control and data descriptors to this list, this list will be submitted to
|
||||
* VPDMA. VPDMA's list parser will go through each descriptor and perform the
|
||||
* required DMA operations
|
||||
*/
|
||||
int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = vpdma_alloc_desc_buf(&list->buf, size);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
list->next = list->buf.addr;
|
||||
|
||||
list->type = type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* once a descriptor list is parsed by VPDMA, we reset the list by emptying it,
|
||||
* to allow new descriptors to be added to the list.
|
||||
*/
|
||||
void vpdma_reset_desc_list(struct vpdma_desc_list *list)
|
||||
{
|
||||
list->next = list->buf.addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* free the buffer allocated fot the VPDMA descriptor list, this should be
|
||||
* called when the user doesn't want to use VPDMA any more.
|
||||
*/
|
||||
void vpdma_free_desc_list(struct vpdma_desc_list *list)
|
||||
{
|
||||
vpdma_free_desc_buf(&list->buf);
|
||||
|
||||
list->next = NULL;
|
||||
}
|
||||
|
||||
static bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num)
|
||||
{
|
||||
return read_reg(vpdma, VPDMA_LIST_STAT_SYNC) & BIT(list_num + 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* submit a list of DMA descriptors to the VPE VPDMA, do not wait for completion
|
||||
*/
|
||||
int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list)
|
||||
{
|
||||
/* we always use the first list */
|
||||
int list_num = 0;
|
||||
int list_size;
|
||||
|
||||
if (vpdma_list_busy(vpdma, list_num))
|
||||
return -EBUSY;
|
||||
|
||||
/* 16-byte granularity */
|
||||
list_size = (list->next - list->buf.addr) >> 4;
|
||||
|
||||
write_reg(vpdma, VPDMA_LIST_ADDR, (u32) list->buf.dma_addr);
|
||||
|
||||
write_reg(vpdma, VPDMA_LIST_ATTR,
|
||||
(list_num << VPDMA_LIST_NUM_SHFT) |
|
||||
(list->type << VPDMA_LIST_TYPE_SHFT) |
|
||||
list_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_cfd(struct vpdma_cfd *cfd)
|
||||
{
|
||||
int class;
|
||||
|
||||
class = cfd_get_class(cfd);
|
||||
|
||||
pr_debug("config descriptor of payload class: %s\n",
|
||||
class == CFD_CLS_BLOCK ? "simple block" :
|
||||
"address data block");
|
||||
|
||||
if (class == CFD_CLS_BLOCK)
|
||||
pr_debug("word0: dst_addr_offset = 0x%08x\n",
|
||||
cfd->dest_addr_offset);
|
||||
|
||||
if (class == CFD_CLS_BLOCK)
|
||||
pr_debug("word1: num_data_wrds = %d\n", cfd->block_len);
|
||||
|
||||
pr_debug("word2: payload_addr = 0x%08x\n", cfd->payload_addr);
|
||||
|
||||
pr_debug("word3: pkt_type = %d, direct = %d, class = %d, dest = %d, "
|
||||
"payload_len = %d\n", cfd_get_pkt_type(cfd),
|
||||
cfd_get_direct(cfd), class, cfd_get_dest(cfd),
|
||||
cfd_get_payload_len(cfd));
|
||||
}
|
||||
|
||||
/*
|
||||
* append a configuration descriptor to the given descriptor list, where the
|
||||
* payload is in the form of a simple data block specified in the descriptor
|
||||
* header, this is used to upload scaler coefficients to the scaler module
|
||||
*/
|
||||
void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client,
|
||||
struct vpdma_buf *blk, u32 dest_offset)
|
||||
{
|
||||
struct vpdma_cfd *cfd;
|
||||
int len = blk->size;
|
||||
|
||||
WARN_ON(blk->dma_addr & VPDMA_DESC_ALIGN);
|
||||
|
||||
cfd = list->next;
|
||||
WARN_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size));
|
||||
|
||||
cfd->dest_addr_offset = dest_offset;
|
||||
cfd->block_len = len;
|
||||
cfd->payload_addr = (u32) blk->dma_addr;
|
||||
cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_BLOCK,
|
||||
client, len >> 4);
|
||||
|
||||
list->next = cfd + 1;
|
||||
|
||||
dump_cfd(cfd);
|
||||
}
|
||||
|
||||
/*
|
||||
* append a configuration descriptor to the given descriptor list, where the
|
||||
* payload is in the address data block format, this is used to a configure a
|
||||
* discontiguous set of MMRs
|
||||
*/
|
||||
void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client,
|
||||
struct vpdma_buf *adb)
|
||||
{
|
||||
struct vpdma_cfd *cfd;
|
||||
unsigned int len = adb->size;
|
||||
|
||||
WARN_ON(len & VPDMA_ADB_SIZE_ALIGN);
|
||||
WARN_ON(adb->dma_addr & VPDMA_DESC_ALIGN);
|
||||
|
||||
cfd = list->next;
|
||||
BUG_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size));
|
||||
|
||||
cfd->w0 = 0;
|
||||
cfd->w1 = 0;
|
||||
cfd->payload_addr = (u32) adb->dma_addr;
|
||||
cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_ADB,
|
||||
client, len >> 4);
|
||||
|
||||
list->next = cfd + 1;
|
||||
|
||||
dump_cfd(cfd);
|
||||
};
|
||||
|
||||
/*
|
||||
* control descriptor format change based on what type of control descriptor it
|
||||
* is, we only use 'sync on channel' control descriptors for now, so assume it's
|
||||
* that
|
||||
*/
|
||||
static void dump_ctd(struct vpdma_ctd *ctd)
|
||||
{
|
||||
pr_debug("control descriptor\n");
|
||||
|
||||
pr_debug("word3: pkt_type = %d, source = %d, ctl_type = %d\n",
|
||||
ctd_get_pkt_type(ctd), ctd_get_source(ctd), ctd_get_ctl(ctd));
|
||||
}
|
||||
|
||||
/*
|
||||
* append a 'sync on channel' type control descriptor to the given descriptor
|
||||
* list, this descriptor stalls the VPDMA list till the time DMA is completed
|
||||
* on the specified channel
|
||||
*/
|
||||
void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list,
|
||||
enum vpdma_channel chan)
|
||||
{
|
||||
struct vpdma_ctd *ctd;
|
||||
|
||||
ctd = list->next;
|
||||
WARN_ON((void *)(ctd + 1) > (list->buf.addr + list->buf.size));
|
||||
|
||||
ctd->w0 = 0;
|
||||
ctd->w1 = 0;
|
||||
ctd->w2 = 0;
|
||||
ctd->type_source_ctl = ctd_type_source_ctl(chan_info[chan].num,
|
||||
CTD_TYPE_SYNC_ON_CHANNEL);
|
||||
|
||||
list->next = ctd + 1;
|
||||
|
||||
dump_ctd(ctd);
|
||||
}
|
||||
|
||||
static void dump_dtd(struct vpdma_dtd *dtd)
|
||||
{
|
||||
int dir, chan;
|
||||
|
||||
dir = dtd_get_dir(dtd);
|
||||
chan = dtd_get_chan(dtd);
|
||||
|
||||
pr_debug("%s data transfer descriptor for channel %d\n",
|
||||
dir == DTD_DIR_OUT ? "outbound" : "inbound", chan);
|
||||
|
||||
pr_debug("word0: data_type = %d, notify = %d, field = %d, 1D = %d, "
|
||||
"even_ln_skp = %d, odd_ln_skp = %d, line_stride = %d\n",
|
||||
dtd_get_data_type(dtd), dtd_get_notify(dtd), dtd_get_field(dtd),
|
||||
dtd_get_1d(dtd), dtd_get_even_line_skip(dtd),
|
||||
dtd_get_odd_line_skip(dtd), dtd_get_line_stride(dtd));
|
||||
|
||||
if (dir == DTD_DIR_IN)
|
||||
pr_debug("word1: line_length = %d, xfer_height = %d\n",
|
||||
dtd_get_line_length(dtd), dtd_get_xfer_height(dtd));
|
||||
|
||||
pr_debug("word2: start_addr = 0x%08x\n", dtd->start_addr);
|
||||
|
||||
pr_debug("word3: pkt_type = %d, mode = %d, dir = %d, chan = %d, "
|
||||
"pri = %d, next_chan = %d\n", dtd_get_pkt_type(dtd),
|
||||
dtd_get_mode(dtd), dir, chan, dtd_get_priority(dtd),
|
||||
dtd_get_next_chan(dtd));
|
||||
|
||||
if (dir == DTD_DIR_IN)
|
||||
pr_debug("word4: frame_width = %d, frame_height = %d\n",
|
||||
dtd_get_frame_width(dtd), dtd_get_frame_height(dtd));
|
||||
else
|
||||
pr_debug("word4: desc_write_addr = 0x%08x, write_desc = %d, "
|
||||
"drp_data = %d, use_desc_reg = %d\n",
|
||||
dtd_get_desc_write_addr(dtd), dtd_get_write_desc(dtd),
|
||||
dtd_get_drop_data(dtd), dtd_get_use_desc(dtd));
|
||||
|
||||
if (dir == DTD_DIR_IN)
|
||||
pr_debug("word5: hor_start = %d, ver_start = %d\n",
|
||||
dtd_get_h_start(dtd), dtd_get_v_start(dtd));
|
||||
else
|
||||
pr_debug("word5: max_width %d, max_height %d\n",
|
||||
dtd_get_max_width(dtd), dtd_get_max_height(dtd));
|
||||
|
||||
pr_debug("word6: client specfic attr0 = 0x%08x\n", dtd->client_attr0);
|
||||
pr_debug("word7: client specfic attr1 = 0x%08x\n", dtd->client_attr1);
|
||||
}
|
||||
|
||||
/*
|
||||
* append an outbound data transfer descriptor to the given descriptor list,
|
||||
* this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel
|
||||
*/
|
||||
void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,
|
||||
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
|
||||
enum vpdma_channel chan, u32 flags)
|
||||
{
|
||||
int priority = 0;
|
||||
int field = 0;
|
||||
int notify = 1;
|
||||
int channel, next_chan;
|
||||
int depth = fmt->depth;
|
||||
int stride;
|
||||
struct vpdma_dtd *dtd;
|
||||
|
||||
channel = next_chan = chan_info[chan].num;
|
||||
|
||||
if (fmt->data_type == DATA_TYPE_C420)
|
||||
depth = 8;
|
||||
|
||||
stride = (depth * c_rect->width) >> 3;
|
||||
dma_addr += (c_rect->left * depth) >> 3;
|
||||
|
||||
dtd = list->next;
|
||||
WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size));
|
||||
|
||||
dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type,
|
||||
notify,
|
||||
field,
|
||||
!!(flags & VPDMA_DATA_FRAME_1D),
|
||||
!!(flags & VPDMA_DATA_EVEN_LINE_SKIP),
|
||||
!!(flags & VPDMA_DATA_ODD_LINE_SKIP),
|
||||
stride);
|
||||
dtd->w1 = 0;
|
||||
dtd->start_addr = (u32) dma_addr;
|
||||
dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED),
|
||||
DTD_DIR_OUT, channel, priority, next_chan);
|
||||
dtd->desc_write_addr = dtd_desc_write_addr(0, 0, 0, 0);
|
||||
dtd->max_width_height = dtd_max_width_height(MAX_OUT_WIDTH_1920,
|
||||
MAX_OUT_HEIGHT_1080);
|
||||
dtd->client_attr0 = 0;
|
||||
dtd->client_attr1 = 0;
|
||||
|
||||
list->next = dtd + 1;
|
||||
|
||||
dump_dtd(dtd);
|
||||
}
|
||||
|
||||
/*
|
||||
* append an inbound data transfer descriptor to the given descriptor list,
|
||||
* this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel
|
||||
*/
|
||||
void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width,
|
||||
int frame_height, struct v4l2_rect *c_rect,
|
||||
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
|
||||
enum vpdma_channel chan, int field, u32 flags)
|
||||
{
|
||||
int priority = 0;
|
||||
int notify = 1;
|
||||
int depth = fmt->depth;
|
||||
int channel, next_chan;
|
||||
int stride;
|
||||
int height = c_rect->height;
|
||||
struct vpdma_dtd *dtd;
|
||||
|
||||
channel = next_chan = chan_info[chan].num;
|
||||
|
||||
if (fmt->data_type == DATA_TYPE_C420) {
|
||||
height >>= 1;
|
||||
frame_height >>= 1;
|
||||
depth = 8;
|
||||
}
|
||||
|
||||
stride = (depth * c_rect->width) >> 3;
|
||||
dma_addr += (c_rect->left * depth) >> 3;
|
||||
|
||||
dtd = list->next;
|
||||
WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size));
|
||||
|
||||
dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type,
|
||||
notify,
|
||||
field,
|
||||
!!(flags & VPDMA_DATA_FRAME_1D),
|
||||
!!(flags & VPDMA_DATA_EVEN_LINE_SKIP),
|
||||
!!(flags & VPDMA_DATA_ODD_LINE_SKIP),
|
||||
stride);
|
||||
|
||||
dtd->xfer_length_height = dtd_xfer_length_height(c_rect->width, height);
|
||||
dtd->start_addr = (u32) dma_addr;
|
||||
dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED),
|
||||
DTD_DIR_IN, channel, priority, next_chan);
|
||||
dtd->frame_width_height = dtd_frame_width_height(frame_width,
|
||||
frame_height);
|
||||
dtd->start_h_v = dtd_start_h_v(c_rect->left, c_rect->top);
|
||||
dtd->client_attr0 = 0;
|
||||
dtd->client_attr1 = 0;
|
||||
|
||||
list->next = dtd + 1;
|
||||
|
||||
dump_dtd(dtd);
|
||||
}
|
||||
|
||||
/* set or clear the mask for list complete interrupt */
|
||||
void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
|
||||
bool enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = read_reg(vpdma, VPDMA_INT_LIST0_MASK);
|
||||
if (enable)
|
||||
val |= (1 << (list_num * 2));
|
||||
else
|
||||
val &= ~(1 << (list_num * 2));
|
||||
write_reg(vpdma, VPDMA_INT_LIST0_MASK, val);
|
||||
}
|
||||
|
||||
/* clear previosuly occured list intterupts in the LIST_STAT register */
|
||||
void vpdma_clear_list_stat(struct vpdma_data *vpdma)
|
||||
{
|
||||
write_reg(vpdma, VPDMA_INT_LIST0_STAT,
|
||||
read_reg(vpdma, VPDMA_INT_LIST0_STAT));
|
||||
}
|
||||
|
||||
/*
|
||||
* configures the output mode of the line buffer for the given client, the
|
||||
* line buffer content can either be mirrored(each line repeated twice) or
|
||||
* passed to the client as is
|
||||
*/
|
||||
void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode,
|
||||
enum vpdma_channel chan)
|
||||
{
|
||||
int client_cstat = chan_info[chan].cstat_offset;
|
||||
|
||||
write_field_reg(vpdma, client_cstat, line_mode,
|
||||
VPDMA_CSTAT_LINE_MODE_MASK, VPDMA_CSTAT_LINE_MODE_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* configures the event which should trigger VPDMA transfer for the given
|
||||
* client
|
||||
*/
|
||||
void vpdma_set_frame_start_event(struct vpdma_data *vpdma,
|
||||
enum vpdma_frame_start_event fs_event,
|
||||
enum vpdma_channel chan)
|
||||
{
|
||||
int client_cstat = chan_info[chan].cstat_offset;
|
||||
|
||||
write_field_reg(vpdma, client_cstat, fs_event,
|
||||
VPDMA_CSTAT_FRAME_START_MASK, VPDMA_CSTAT_FRAME_START_SHIFT);
|
||||
}
|
||||
|
||||
static void vpdma_firmware_cb(const struct firmware *f, void *context)
|
||||
{
|
||||
struct vpdma_data *vpdma = context;
|
||||
struct vpdma_buf fw_dma_buf;
|
||||
int i, r;
|
||||
|
||||
dev_dbg(&vpdma->pdev->dev, "firmware callback\n");
|
||||
|
||||
if (!f || !f->data) {
|
||||
dev_err(&vpdma->pdev->dev, "couldn't get firmware\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* already initialized */
|
||||
if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK,
|
||||
VPDMA_LIST_RDY_SHFT)) {
|
||||
vpdma->ready = true;
|
||||
return;
|
||||
}
|
||||
|
||||
r = vpdma_alloc_desc_buf(&fw_dma_buf, f->size);
|
||||
if (r) {
|
||||
dev_err(&vpdma->pdev->dev,
|
||||
"failed to allocate dma buffer for firmware\n");
|
||||
goto rel_fw;
|
||||
}
|
||||
|
||||
memcpy(fw_dma_buf.addr, f->data, f->size);
|
||||
|
||||
vpdma_map_desc_buf(vpdma, &fw_dma_buf);
|
||||
|
||||
write_reg(vpdma, VPDMA_LIST_ADDR, (u32) fw_dma_buf.dma_addr);
|
||||
|
||||
for (i = 0; i < 100; i++) { /* max 1 second */
|
||||
msleep_interruptible(10);
|
||||
|
||||
if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK,
|
||||
VPDMA_LIST_RDY_SHFT))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 100) {
|
||||
dev_err(&vpdma->pdev->dev, "firmware upload failed\n");
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
vpdma->ready = true;
|
||||
|
||||
free_buf:
|
||||
vpdma_unmap_desc_buf(vpdma, &fw_dma_buf);
|
||||
|
||||
vpdma_free_desc_buf(&fw_dma_buf);
|
||||
rel_fw:
|
||||
release_firmware(f);
|
||||
}
|
||||
|
||||
static int vpdma_load_firmware(struct vpdma_data *vpdma)
|
||||
{
|
||||
int r;
|
||||
struct device *dev = &vpdma->pdev->dev;
|
||||
|
||||
r = request_firmware_nowait(THIS_MODULE, 1,
|
||||
(const char *) VPDMA_FIRMWARE, dev, GFP_KERNEL, vpdma,
|
||||
vpdma_firmware_cb);
|
||||
if (r) {
|
||||
dev_err(dev, "firmware not available %s\n", VPDMA_FIRMWARE);
|
||||
return r;
|
||||
} else {
|
||||
dev_info(dev, "loading firmware %s\n", VPDMA_FIRMWARE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct vpdma_data *vpdma_create(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct vpdma_data *vpdma;
|
||||
int r;
|
||||
|
||||
dev_dbg(&pdev->dev, "vpdma_create\n");
|
||||
|
||||
vpdma = devm_kzalloc(&pdev->dev, sizeof(*vpdma), GFP_KERNEL);
|
||||
if (!vpdma) {
|
||||
dev_err(&pdev->dev, "couldn't alloc vpdma_dev\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
vpdma->pdev = pdev;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma");
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "missing platform resources data\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
vpdma->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (!vpdma->base) {
|
||||
dev_err(&pdev->dev, "failed to ioremap\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
r = vpdma_load_firmware(vpdma);
|
||||
if (r) {
|
||||
pr_err("failed to load firmware %s\n", VPDMA_FIRMWARE);
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
|
||||
return vpdma;
|
||||
}
|
||||
MODULE_FIRMWARE(VPDMA_FIRMWARE);
|
203
drivers/media/platform/ti-vpe/vpdma.h
Normal file
203
drivers/media/platform/ti-vpe/vpdma.h
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Texas Instruments Inc.
|
||||
*
|
||||
* David Griego, <dagriego@biglakesoftware.com>
|
||||
* Dale Farnsworth, <dale@farnsworth.org>
|
||||
* Archit Taneja, <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __TI_VPDMA_H_
|
||||
#define __TI_VPDMA_H_
|
||||
|
||||
/*
|
||||
* A vpdma_buf tracks the size, DMA address and mapping status of each
|
||||
* driver DMA area.
|
||||
*/
|
||||
struct vpdma_buf {
|
||||
void *addr;
|
||||
dma_addr_t dma_addr;
|
||||
size_t size;
|
||||
bool mapped;
|
||||
};
|
||||
|
||||
struct vpdma_desc_list {
|
||||
struct vpdma_buf buf;
|
||||
void *next;
|
||||
int type;
|
||||
};
|
||||
|
||||
struct vpdma_data {
|
||||
void __iomem *base;
|
||||
|
||||
struct platform_device *pdev;
|
||||
|
||||
/* tells whether vpdma firmware is loaded or not */
|
||||
bool ready;
|
||||
};
|
||||
|
||||
struct vpdma_data_format {
|
||||
int data_type;
|
||||
u8 depth;
|
||||
};
|
||||
|
||||
#define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */
|
||||
|
||||
#define VPDMA_DTD_DESC_SIZE 32 /* 8 words */
|
||||
#define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */
|
||||
|
||||
#define VPDMA_LIST_TYPE_NORMAL 0
|
||||
#define VPDMA_LIST_TYPE_SELF_MODIFYING 1
|
||||
#define VPDMA_LIST_TYPE_DOORBELL 2
|
||||
|
||||
enum vpdma_yuv_formats {
|
||||
VPDMA_DATA_FMT_Y444 = 0,
|
||||
VPDMA_DATA_FMT_Y422,
|
||||
VPDMA_DATA_FMT_Y420,
|
||||
VPDMA_DATA_FMT_C444,
|
||||
VPDMA_DATA_FMT_C422,
|
||||
VPDMA_DATA_FMT_C420,
|
||||
VPDMA_DATA_FMT_YC422,
|
||||
VPDMA_DATA_FMT_YC444,
|
||||
VPDMA_DATA_FMT_CY422,
|
||||
};
|
||||
|
||||
enum vpdma_rgb_formats {
|
||||
VPDMA_DATA_FMT_RGB565 = 0,
|
||||
VPDMA_DATA_FMT_ARGB16_1555,
|
||||
VPDMA_DATA_FMT_ARGB16,
|
||||
VPDMA_DATA_FMT_RGBA16_5551,
|
||||
VPDMA_DATA_FMT_RGBA16,
|
||||
VPDMA_DATA_FMT_ARGB24,
|
||||
VPDMA_DATA_FMT_RGB24,
|
||||
VPDMA_DATA_FMT_ARGB32,
|
||||
VPDMA_DATA_FMT_RGBA24,
|
||||
VPDMA_DATA_FMT_RGBA32,
|
||||
VPDMA_DATA_FMT_BGR565,
|
||||
VPDMA_DATA_FMT_ABGR16_1555,
|
||||
VPDMA_DATA_FMT_ABGR16,
|
||||
VPDMA_DATA_FMT_BGRA16_5551,
|
||||
VPDMA_DATA_FMT_BGRA16,
|
||||
VPDMA_DATA_FMT_ABGR24,
|
||||
VPDMA_DATA_FMT_BGR24,
|
||||
VPDMA_DATA_FMT_ABGR32,
|
||||
VPDMA_DATA_FMT_BGRA24,
|
||||
VPDMA_DATA_FMT_BGRA32,
|
||||
};
|
||||
|
||||
enum vpdma_misc_formats {
|
||||
VPDMA_DATA_FMT_MV = 0,
|
||||
};
|
||||
|
||||
extern const struct vpdma_data_format vpdma_yuv_fmts[];
|
||||
extern const struct vpdma_data_format vpdma_rgb_fmts[];
|
||||
extern const struct vpdma_data_format vpdma_misc_fmts[];
|
||||
|
||||
enum vpdma_frame_start_event {
|
||||
VPDMA_FSEVENT_HDMI_FID = 0,
|
||||
VPDMA_FSEVENT_DVO2_FID,
|
||||
VPDMA_FSEVENT_HDCOMP_FID,
|
||||
VPDMA_FSEVENT_SD_FID,
|
||||
VPDMA_FSEVENT_LM_FID0,
|
||||
VPDMA_FSEVENT_LM_FID1,
|
||||
VPDMA_FSEVENT_LM_FID2,
|
||||
VPDMA_FSEVENT_CHANNEL_ACTIVE,
|
||||
};
|
||||
|
||||
/*
|
||||
* VPDMA channel numbers
|
||||
*/
|
||||
enum vpdma_channel {
|
||||
VPE_CHAN_LUMA1_IN,
|
||||
VPE_CHAN_CHROMA1_IN,
|
||||
VPE_CHAN_LUMA2_IN,
|
||||
VPE_CHAN_CHROMA2_IN,
|
||||
VPE_CHAN_LUMA3_IN,
|
||||
VPE_CHAN_CHROMA3_IN,
|
||||
VPE_CHAN_MV_IN,
|
||||
VPE_CHAN_MV_OUT,
|
||||
VPE_CHAN_LUMA_OUT,
|
||||
VPE_CHAN_CHROMA_OUT,
|
||||
VPE_CHAN_RGB_OUT,
|
||||
};
|
||||
|
||||
/* flags for VPDMA data descriptors */
|
||||
#define VPDMA_DATA_ODD_LINE_SKIP (1 << 0)
|
||||
#define VPDMA_DATA_EVEN_LINE_SKIP (1 << 1)
|
||||
#define VPDMA_DATA_FRAME_1D (1 << 2)
|
||||
#define VPDMA_DATA_MODE_TILED (1 << 3)
|
||||
|
||||
/*
|
||||
* client identifiers used for configuration descriptors
|
||||
*/
|
||||
#define CFD_MMR_CLIENT 0
|
||||
#define CFD_SC_CLIENT 4
|
||||
|
||||
/* Address data block header format */
|
||||
struct vpdma_adb_hdr {
|
||||
u32 offset;
|
||||
u32 nwords;
|
||||
u32 reserved0;
|
||||
u32 reserved1;
|
||||
};
|
||||
|
||||
/* helpers for creating ADB headers for config descriptors MMRs as client */
|
||||
#define ADB_ADDR(dma_buf, str, fld) ((dma_buf)->addr + offsetof(str, fld))
|
||||
#define MMR_ADB_ADDR(buf, str, fld) ADB_ADDR(&(buf), struct str, fld)
|
||||
|
||||
#define VPDMA_SET_MMR_ADB_HDR(buf, str, hdr, regs, offset_a) \
|
||||
do { \
|
||||
struct vpdma_adb_hdr *h; \
|
||||
struct str *adb = NULL; \
|
||||
h = MMR_ADB_ADDR(buf, str, hdr); \
|
||||
h->offset = (offset_a); \
|
||||
h->nwords = sizeof(adb->regs) >> 2; \
|
||||
} while (0)
|
||||
|
||||
/* vpdma descriptor buffer allocation and management */
|
||||
int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size);
|
||||
void vpdma_free_desc_buf(struct vpdma_buf *buf);
|
||||
int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf);
|
||||
void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf);
|
||||
|
||||
/* vpdma descriptor list funcs */
|
||||
int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type);
|
||||
void vpdma_reset_desc_list(struct vpdma_desc_list *list);
|
||||
void vpdma_free_desc_list(struct vpdma_desc_list *list);
|
||||
int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list);
|
||||
|
||||
/* helpers for creating vpdma descriptors */
|
||||
void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client,
|
||||
struct vpdma_buf *blk, u32 dest_offset);
|
||||
void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client,
|
||||
struct vpdma_buf *adb);
|
||||
void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list,
|
||||
enum vpdma_channel chan);
|
||||
void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,
|
||||
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
|
||||
enum vpdma_channel chan, u32 flags);
|
||||
void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width,
|
||||
int frame_height, struct v4l2_rect *c_rect,
|
||||
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
|
||||
enum vpdma_channel chan, int field, u32 flags);
|
||||
|
||||
/* vpdma list interrupt management */
|
||||
void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
|
||||
bool enable);
|
||||
void vpdma_clear_list_stat(struct vpdma_data *vpdma);
|
||||
|
||||
/* vpdma client configuration */
|
||||
void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode,
|
||||
enum vpdma_channel chan);
|
||||
void vpdma_set_frame_start_event(struct vpdma_data *vpdma,
|
||||
enum vpdma_frame_start_event fs_event, enum vpdma_channel chan);
|
||||
|
||||
void vpdma_dump_regs(struct vpdma_data *vpdma);
|
||||
|
||||
/* initialize vpdma, passed with VPE's platform device pointer */
|
||||
struct vpdma_data *vpdma_create(struct platform_device *pdev);
|
||||
|
||||
#endif
|
641
drivers/media/platform/ti-vpe/vpdma_priv.h
Normal file
641
drivers/media/platform/ti-vpe/vpdma_priv.h
Normal file
@ -0,0 +1,641 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Texas Instruments Inc.
|
||||
*
|
||||
* David Griego, <dagriego@biglakesoftware.com>
|
||||
* Dale Farnsworth, <dale@farnsworth.org>
|
||||
* Archit Taneja, <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _TI_VPDMA_PRIV_H_
|
||||
#define _TI_VPDMA_PRIV_H_
|
||||
|
||||
/*
|
||||
* VPDMA Register offsets
|
||||
*/
|
||||
|
||||
/* Top level */
|
||||
#define VPDMA_PID 0x00
|
||||
#define VPDMA_LIST_ADDR 0x04
|
||||
#define VPDMA_LIST_ATTR 0x08
|
||||
#define VPDMA_LIST_STAT_SYNC 0x0c
|
||||
#define VPDMA_BG_RGB 0x18
|
||||
#define VPDMA_BG_YUV 0x1c
|
||||
#define VPDMA_SETUP 0x30
|
||||
#define VPDMA_MAX_SIZE1 0x34
|
||||
#define VPDMA_MAX_SIZE2 0x38
|
||||
#define VPDMA_MAX_SIZE3 0x3c
|
||||
|
||||
/* Interrupts */
|
||||
#define VPDMA_INT_CHAN_STAT(grp) (0x40 + grp * 8)
|
||||
#define VPDMA_INT_CHAN_MASK(grp) (VPDMA_INT_CHAN_STAT(grp) + 4)
|
||||
#define VPDMA_INT_CLIENT0_STAT 0x78
|
||||
#define VPDMA_INT_CLIENT0_MASK 0x7c
|
||||
#define VPDMA_INT_CLIENT1_STAT 0x80
|
||||
#define VPDMA_INT_CLIENT1_MASK 0x84
|
||||
#define VPDMA_INT_LIST0_STAT 0x88
|
||||
#define VPDMA_INT_LIST0_MASK 0x8c
|
||||
|
||||
#define VPDMA_PERFMON(i) (0x200 + i * 4)
|
||||
|
||||
/* VPE specific client registers */
|
||||
#define VPDMA_DEI_CHROMA1_CSTAT 0x0300
|
||||
#define VPDMA_DEI_LUMA1_CSTAT 0x0304
|
||||
#define VPDMA_DEI_LUMA2_CSTAT 0x0308
|
||||
#define VPDMA_DEI_CHROMA2_CSTAT 0x030c
|
||||
#define VPDMA_DEI_LUMA3_CSTAT 0x0310
|
||||
#define VPDMA_DEI_CHROMA3_CSTAT 0x0314
|
||||
#define VPDMA_DEI_MV_IN_CSTAT 0x0330
|
||||
#define VPDMA_DEI_MV_OUT_CSTAT 0x033c
|
||||
#define VPDMA_VIP_UP_Y_CSTAT 0x0390
|
||||
#define VPDMA_VIP_UP_UV_CSTAT 0x0394
|
||||
#define VPDMA_VPI_CTL_CSTAT 0x03d0
|
||||
|
||||
/* Reg field info for VPDMA_CLIENT_CSTAT registers */
|
||||
#define VPDMA_CSTAT_LINE_MODE_MASK 0x03
|
||||
#define VPDMA_CSTAT_LINE_MODE_SHIFT 8
|
||||
#define VPDMA_CSTAT_FRAME_START_MASK 0xf
|
||||
#define VPDMA_CSTAT_FRAME_START_SHIFT 10
|
||||
|
||||
#define VPDMA_LIST_NUM_MASK 0x07
|
||||
#define VPDMA_LIST_NUM_SHFT 24
|
||||
#define VPDMA_LIST_STOP_SHFT 20
|
||||
#define VPDMA_LIST_RDY_MASK 0x01
|
||||
#define VPDMA_LIST_RDY_SHFT 19
|
||||
#define VPDMA_LIST_TYPE_MASK 0x03
|
||||
#define VPDMA_LIST_TYPE_SHFT 16
|
||||
#define VPDMA_LIST_SIZE_MASK 0xffff
|
||||
|
||||
/* VPDMA data type values for data formats */
|
||||
#define DATA_TYPE_Y444 0x0
|
||||
#define DATA_TYPE_Y422 0x1
|
||||
#define DATA_TYPE_Y420 0x2
|
||||
#define DATA_TYPE_C444 0x4
|
||||
#define DATA_TYPE_C422 0x5
|
||||
#define DATA_TYPE_C420 0x6
|
||||
#define DATA_TYPE_YC422 0x7
|
||||
#define DATA_TYPE_YC444 0x8
|
||||
#define DATA_TYPE_CY422 0x23
|
||||
|
||||
#define DATA_TYPE_RGB16_565 0x0
|
||||
#define DATA_TYPE_ARGB_1555 0x1
|
||||
#define DATA_TYPE_ARGB_4444 0x2
|
||||
#define DATA_TYPE_RGBA_5551 0x3
|
||||
#define DATA_TYPE_RGBA_4444 0x4
|
||||
#define DATA_TYPE_ARGB24_6666 0x5
|
||||
#define DATA_TYPE_RGB24_888 0x6
|
||||
#define DATA_TYPE_ARGB32_8888 0x7
|
||||
#define DATA_TYPE_RGBA24_6666 0x8
|
||||
#define DATA_TYPE_RGBA32_8888 0x9
|
||||
#define DATA_TYPE_BGR16_565 0x10
|
||||
#define DATA_TYPE_ABGR_1555 0x11
|
||||
#define DATA_TYPE_ABGR_4444 0x12
|
||||
#define DATA_TYPE_BGRA_5551 0x13
|
||||
#define DATA_TYPE_BGRA_4444 0x14
|
||||
#define DATA_TYPE_ABGR24_6666 0x15
|
||||
#define DATA_TYPE_BGR24_888 0x16
|
||||
#define DATA_TYPE_ABGR32_8888 0x17
|
||||
#define DATA_TYPE_BGRA24_6666 0x18
|
||||
#define DATA_TYPE_BGRA32_8888 0x19
|
||||
|
||||
#define DATA_TYPE_MV 0x3
|
||||
|
||||
/* VPDMA channel numbers(only VPE channels for now) */
|
||||
#define VPE_CHAN_NUM_LUMA1_IN 0
|
||||
#define VPE_CHAN_NUM_CHROMA1_IN 1
|
||||
#define VPE_CHAN_NUM_LUMA2_IN 2
|
||||
#define VPE_CHAN_NUM_CHROMA2_IN 3
|
||||
#define VPE_CHAN_NUM_LUMA3_IN 4
|
||||
#define VPE_CHAN_NUM_CHROMA3_IN 5
|
||||
#define VPE_CHAN_NUM_MV_IN 12
|
||||
#define VPE_CHAN_NUM_MV_OUT 15
|
||||
#define VPE_CHAN_NUM_LUMA_OUT 102
|
||||
#define VPE_CHAN_NUM_CHROMA_OUT 103
|
||||
#define VPE_CHAN_NUM_RGB_OUT 106
|
||||
|
||||
/*
|
||||
* a VPDMA address data block payload for a configuration descriptor needs to
|
||||
* have each sub block length as a multiple of 16 bytes. Therefore, the overall
|
||||
* size of the payload also needs to be a multiple of 16 bytes. The sub block
|
||||
* lengths should be ensured to be aligned by the VPDMA user.
|
||||
*/
|
||||
#define VPDMA_ADB_SIZE_ALIGN 0x0f
|
||||
|
||||
/*
|
||||
* data transfer descriptor
|
||||
*/
|
||||
struct vpdma_dtd {
|
||||
u32 type_ctl_stride;
|
||||
union {
|
||||
u32 xfer_length_height;
|
||||
u32 w1;
|
||||
};
|
||||
dma_addr_t start_addr;
|
||||
u32 pkt_ctl;
|
||||
union {
|
||||
u32 frame_width_height; /* inbound */
|
||||
dma_addr_t desc_write_addr; /* outbound */
|
||||
};
|
||||
union {
|
||||
u32 start_h_v; /* inbound */
|
||||
u32 max_width_height; /* outbound */
|
||||
};
|
||||
u32 client_attr0;
|
||||
u32 client_attr1;
|
||||
};
|
||||
|
||||
/* Data Transfer Descriptor specifics */
|
||||
#define DTD_NO_NOTIFY 0
|
||||
#define DTD_NOTIFY 1
|
||||
|
||||
#define DTD_PKT_TYPE 0xa
|
||||
#define DTD_DIR_IN 0
|
||||
#define DTD_DIR_OUT 1
|
||||
|
||||
/* type_ctl_stride */
|
||||
#define DTD_DATA_TYPE_MASK 0x3f
|
||||
#define DTD_DATA_TYPE_SHFT 26
|
||||
#define DTD_NOTIFY_MASK 0x01
|
||||
#define DTD_NOTIFY_SHFT 25
|
||||
#define DTD_FIELD_MASK 0x01
|
||||
#define DTD_FIELD_SHFT 24
|
||||
#define DTD_1D_MASK 0x01
|
||||
#define DTD_1D_SHFT 23
|
||||
#define DTD_EVEN_LINE_SKIP_MASK 0x01
|
||||
#define DTD_EVEN_LINE_SKIP_SHFT 20
|
||||
#define DTD_ODD_LINE_SKIP_MASK 0x01
|
||||
#define DTD_ODD_LINE_SKIP_SHFT 16
|
||||
#define DTD_LINE_STRIDE_MASK 0xffff
|
||||
#define DTD_LINE_STRIDE_SHFT 0
|
||||
|
||||
/* xfer_length_height */
|
||||
#define DTD_LINE_LENGTH_MASK 0xffff
|
||||
#define DTD_LINE_LENGTH_SHFT 16
|
||||
#define DTD_XFER_HEIGHT_MASK 0xffff
|
||||
#define DTD_XFER_HEIGHT_SHFT 0
|
||||
|
||||
/* pkt_ctl */
|
||||
#define DTD_PKT_TYPE_MASK 0x1f
|
||||
#define DTD_PKT_TYPE_SHFT 27
|
||||
#define DTD_MODE_MASK 0x01
|
||||
#define DTD_MODE_SHFT 26
|
||||
#define DTD_DIR_MASK 0x01
|
||||
#define DTD_DIR_SHFT 25
|
||||
#define DTD_CHAN_MASK 0x01ff
|
||||
#define DTD_CHAN_SHFT 16
|
||||
#define DTD_PRI_MASK 0x0f
|
||||
#define DTD_PRI_SHFT 9
|
||||
#define DTD_NEXT_CHAN_MASK 0x01ff
|
||||
#define DTD_NEXT_CHAN_SHFT 0
|
||||
|
||||
/* frame_width_height */
|
||||
#define DTD_FRAME_WIDTH_MASK 0xffff
|
||||
#define DTD_FRAME_WIDTH_SHFT 16
|
||||
#define DTD_FRAME_HEIGHT_MASK 0xffff
|
||||
#define DTD_FRAME_HEIGHT_SHFT 0
|
||||
|
||||
/* start_h_v */
|
||||
#define DTD_H_START_MASK 0xffff
|
||||
#define DTD_H_START_SHFT 16
|
||||
#define DTD_V_START_MASK 0xffff
|
||||
#define DTD_V_START_SHFT 0
|
||||
|
||||
#define DTD_DESC_START_SHIFT 5
|
||||
#define DTD_WRITE_DESC_MASK 0x01
|
||||
#define DTD_WRITE_DESC_SHIFT 2
|
||||
#define DTD_DROP_DATA_MASK 0x01
|
||||
#define DTD_DROP_DATA_SHIFT 1
|
||||
#define DTD_USE_DESC_MASK 0x01
|
||||
#define DTD_USE_DESC_SHIFT 0
|
||||
|
||||
/* max_width_height */
|
||||
#define DTD_MAX_WIDTH_MASK 0x07
|
||||
#define DTD_MAX_WIDTH_SHFT 4
|
||||
#define DTD_MAX_HEIGHT_MASK 0x07
|
||||
#define DTD_MAX_HEIGHT_SHFT 0
|
||||
|
||||
/* max width configurations */
|
||||
/* unlimited width */
|
||||
#define MAX_OUT_WIDTH_UNLIMITED 0
|
||||
/* as specified in max_size1 reg */
|
||||
#define MAX_OUT_WIDTH_REG1 1
|
||||
/* as specified in max_size2 reg */
|
||||
#define MAX_OUT_WIDTH_REG2 2
|
||||
/* as specified in max_size3 reg */
|
||||
#define MAX_OUT_WIDTH_REG3 3
|
||||
/* maximum of 352 pixels as width */
|
||||
#define MAX_OUT_WIDTH_352 4
|
||||
/* maximum of 768 pixels as width */
|
||||
#define MAX_OUT_WIDTH_768 5
|
||||
/* maximum of 1280 pixels width */
|
||||
#define MAX_OUT_WIDTH_1280 6
|
||||
/* maximum of 1920 pixels as width */
|
||||
#define MAX_OUT_WIDTH_1920 7
|
||||
|
||||
/* max height configurations */
|
||||
/* unlimited height */
|
||||
#define MAX_OUT_HEIGHT_UNLIMITED 0
|
||||
/* as specified in max_size1 reg */
|
||||
#define MAX_OUT_HEIGHT_REG1 1
|
||||
/* as specified in max_size2 reg */
|
||||
#define MAX_OUT_HEIGHT_REG2 2
|
||||
/* as specified in max_size3 reg */
|
||||
#define MAX_OUT_HEIGHT_REG3 3
|
||||
/* maximum of 288 lines as height */
|
||||
#define MAX_OUT_HEIGHT_288 4
|
||||
/* maximum of 576 lines as height */
|
||||
#define MAX_OUT_HEIGHT_576 5
|
||||
/* maximum of 720 lines as height */
|
||||
#define MAX_OUT_HEIGHT_720 6
|
||||
/* maximum of 1080 lines as height */
|
||||
#define MAX_OUT_HEIGHT_1080 7
|
||||
|
||||
static inline u32 dtd_type_ctl_stride(int type, bool notify, int field,
|
||||
bool one_d, bool even_line_skip, bool odd_line_skip,
|
||||
int line_stride)
|
||||
{
|
||||
return (type << DTD_DATA_TYPE_SHFT) | (notify << DTD_NOTIFY_SHFT) |
|
||||
(field << DTD_FIELD_SHFT) | (one_d << DTD_1D_SHFT) |
|
||||
(even_line_skip << DTD_EVEN_LINE_SKIP_SHFT) |
|
||||
(odd_line_skip << DTD_ODD_LINE_SKIP_SHFT) |
|
||||
line_stride;
|
||||
}
|
||||
|
||||
static inline u32 dtd_xfer_length_height(int line_length, int xfer_height)
|
||||
{
|
||||
return (line_length << DTD_LINE_LENGTH_SHFT) | xfer_height;
|
||||
}
|
||||
|
||||
static inline u32 dtd_pkt_ctl(bool mode, bool dir, int chan, int pri,
|
||||
int next_chan)
|
||||
{
|
||||
return (DTD_PKT_TYPE << DTD_PKT_TYPE_SHFT) | (mode << DTD_MODE_SHFT) |
|
||||
(dir << DTD_DIR_SHFT) | (chan << DTD_CHAN_SHFT) |
|
||||
(pri << DTD_PRI_SHFT) | next_chan;
|
||||
}
|
||||
|
||||
static inline u32 dtd_frame_width_height(int width, int height)
|
||||
{
|
||||
return (width << DTD_FRAME_WIDTH_SHFT) | height;
|
||||
}
|
||||
|
||||
static inline u32 dtd_desc_write_addr(unsigned int addr, bool write_desc,
|
||||
bool drop_data, bool use_desc)
|
||||
{
|
||||
return (addr << DTD_DESC_START_SHIFT) |
|
||||
(write_desc << DTD_WRITE_DESC_SHIFT) |
|
||||
(drop_data << DTD_DROP_DATA_SHIFT) |
|
||||
use_desc;
|
||||
}
|
||||
|
||||
static inline u32 dtd_start_h_v(int h_start, int v_start)
|
||||
{
|
||||
return (h_start << DTD_H_START_SHFT) | v_start;
|
||||
}
|
||||
|
||||
static inline u32 dtd_max_width_height(int max_width, int max_height)
|
||||
{
|
||||
return (max_width << DTD_MAX_WIDTH_SHFT) | max_height;
|
||||
}
|
||||
|
||||
static inline int dtd_get_data_type(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->type_ctl_stride >> DTD_DATA_TYPE_SHFT;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_notify(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->type_ctl_stride >> DTD_NOTIFY_SHFT) & DTD_NOTIFY_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_field(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->type_ctl_stride >> DTD_FIELD_SHFT) & DTD_FIELD_MASK;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_1d(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->type_ctl_stride >> DTD_1D_SHFT) & DTD_1D_MASK;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_even_line_skip(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->type_ctl_stride >> DTD_EVEN_LINE_SKIP_SHFT)
|
||||
& DTD_EVEN_LINE_SKIP_MASK;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_odd_line_skip(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->type_ctl_stride >> DTD_ODD_LINE_SKIP_SHFT)
|
||||
& DTD_ODD_LINE_SKIP_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_line_stride(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->type_ctl_stride & DTD_LINE_STRIDE_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_line_length(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->xfer_length_height >> DTD_LINE_LENGTH_SHFT;
|
||||
}
|
||||
|
||||
static inline int dtd_get_xfer_height(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->xfer_length_height & DTD_XFER_HEIGHT_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_pkt_type(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->pkt_ctl >> DTD_PKT_TYPE_SHFT;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_mode(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->pkt_ctl >> DTD_MODE_SHFT) & DTD_MODE_MASK;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_dir(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->pkt_ctl >> DTD_DIR_SHFT) & DTD_DIR_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_chan(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->pkt_ctl >> DTD_CHAN_SHFT) & DTD_CHAN_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_priority(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->pkt_ctl >> DTD_PRI_SHFT) & DTD_PRI_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_next_chan(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->pkt_ctl >> DTD_NEXT_CHAN_SHFT) & DTD_NEXT_CHAN_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_frame_width(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->frame_width_height >> DTD_FRAME_WIDTH_SHFT;
|
||||
}
|
||||
|
||||
static inline int dtd_get_frame_height(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->frame_width_height & DTD_FRAME_HEIGHT_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_desc_write_addr(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->desc_write_addr >> DTD_DESC_START_SHIFT;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_write_desc(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->desc_write_addr >> DTD_WRITE_DESC_SHIFT) &
|
||||
DTD_WRITE_DESC_MASK;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_drop_data(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->desc_write_addr >> DTD_DROP_DATA_SHIFT) &
|
||||
DTD_DROP_DATA_MASK;
|
||||
}
|
||||
|
||||
static inline bool dtd_get_use_desc(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->desc_write_addr & DTD_USE_DESC_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_h_start(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->start_h_v >> DTD_H_START_SHFT;
|
||||
}
|
||||
|
||||
static inline int dtd_get_v_start(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return dtd->start_h_v & DTD_V_START_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_max_width(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->max_width_height >> DTD_MAX_WIDTH_SHFT) &
|
||||
DTD_MAX_WIDTH_MASK;
|
||||
}
|
||||
|
||||
static inline int dtd_get_max_height(struct vpdma_dtd *dtd)
|
||||
{
|
||||
return (dtd->max_width_height >> DTD_MAX_HEIGHT_SHFT) &
|
||||
DTD_MAX_HEIGHT_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* configuration descriptor
|
||||
*/
|
||||
struct vpdma_cfd {
|
||||
union {
|
||||
u32 dest_addr_offset;
|
||||
u32 w0;
|
||||
};
|
||||
union {
|
||||
u32 block_len; /* in words */
|
||||
u32 w1;
|
||||
};
|
||||
u32 payload_addr;
|
||||
u32 ctl_payload_len; /* in words */
|
||||
};
|
||||
|
||||
/* Configuration descriptor specifics */
|
||||
|
||||
#define CFD_PKT_TYPE 0xb
|
||||
|
||||
#define CFD_DIRECT 1
|
||||
#define CFD_INDIRECT 0
|
||||
#define CFD_CLS_ADB 0
|
||||
#define CFD_CLS_BLOCK 1
|
||||
|
||||
/* block_len */
|
||||
#define CFD__BLOCK_LEN_MASK 0xffff
|
||||
#define CFD__BLOCK_LEN_SHFT 0
|
||||
|
||||
/* ctl_payload_len */
|
||||
#define CFD_PKT_TYPE_MASK 0x1f
|
||||
#define CFD_PKT_TYPE_SHFT 27
|
||||
#define CFD_DIRECT_MASK 0x01
|
||||
#define CFD_DIRECT_SHFT 26
|
||||
#define CFD_CLASS_MASK 0x03
|
||||
#define CFD_CLASS_SHFT 24
|
||||
#define CFD_DEST_MASK 0xff
|
||||
#define CFD_DEST_SHFT 16
|
||||
#define CFD_PAYLOAD_LEN_MASK 0xffff
|
||||
#define CFD_PAYLOAD_LEN_SHFT 0
|
||||
|
||||
static inline u32 cfd_pkt_payload_len(bool direct, int cls, int dest,
|
||||
int payload_len)
|
||||
{
|
||||
return (CFD_PKT_TYPE << CFD_PKT_TYPE_SHFT) |
|
||||
(direct << CFD_DIRECT_SHFT) |
|
||||
(cls << CFD_CLASS_SHFT) |
|
||||
(dest << CFD_DEST_SHFT) |
|
||||
payload_len;
|
||||
}
|
||||
|
||||
static inline int cfd_get_pkt_type(struct vpdma_cfd *cfd)
|
||||
{
|
||||
return cfd->ctl_payload_len >> CFD_PKT_TYPE_SHFT;
|
||||
}
|
||||
|
||||
static inline bool cfd_get_direct(struct vpdma_cfd *cfd)
|
||||
{
|
||||
return (cfd->ctl_payload_len >> CFD_DIRECT_SHFT) & CFD_DIRECT_MASK;
|
||||
}
|
||||
|
||||
static inline bool cfd_get_class(struct vpdma_cfd *cfd)
|
||||
{
|
||||
return (cfd->ctl_payload_len >> CFD_CLASS_SHFT) & CFD_CLASS_MASK;
|
||||
}
|
||||
|
||||
static inline int cfd_get_dest(struct vpdma_cfd *cfd)
|
||||
{
|
||||
return (cfd->ctl_payload_len >> CFD_DEST_SHFT) & CFD_DEST_MASK;
|
||||
}
|
||||
|
||||
static inline int cfd_get_payload_len(struct vpdma_cfd *cfd)
|
||||
{
|
||||
return cfd->ctl_payload_len & CFD_PAYLOAD_LEN_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* control descriptor
|
||||
*/
|
||||
struct vpdma_ctd {
|
||||
union {
|
||||
u32 timer_value;
|
||||
u32 list_addr;
|
||||
u32 w0;
|
||||
};
|
||||
union {
|
||||
u32 pixel_line_count;
|
||||
u32 list_size;
|
||||
u32 w1;
|
||||
};
|
||||
union {
|
||||
u32 event;
|
||||
u32 fid_ctl;
|
||||
u32 w2;
|
||||
};
|
||||
u32 type_source_ctl;
|
||||
};
|
||||
|
||||
/* control descriptor types */
|
||||
#define CTD_TYPE_SYNC_ON_CLIENT 0
|
||||
#define CTD_TYPE_SYNC_ON_LIST 1
|
||||
#define CTD_TYPE_SYNC_ON_EXT 2
|
||||
#define CTD_TYPE_SYNC_ON_LM_TIMER 3
|
||||
#define CTD_TYPE_SYNC_ON_CHANNEL 4
|
||||
#define CTD_TYPE_CHNG_CLIENT_IRQ 5
|
||||
#define CTD_TYPE_SEND_IRQ 6
|
||||
#define CTD_TYPE_RELOAD_LIST 7
|
||||
#define CTD_TYPE_ABORT_CHANNEL 8
|
||||
|
||||
#define CTD_PKT_TYPE 0xc
|
||||
|
||||
/* timer_value */
|
||||
#define CTD_TIMER_VALUE_MASK 0xffff
|
||||
#define CTD_TIMER_VALUE_SHFT 0
|
||||
|
||||
/* pixel_line_count */
|
||||
#define CTD_PIXEL_COUNT_MASK 0xffff
|
||||
#define CTD_PIXEL_COUNT_SHFT 16
|
||||
#define CTD_LINE_COUNT_MASK 0xffff
|
||||
#define CTD_LINE_COUNT_SHFT 0
|
||||
|
||||
/* list_size */
|
||||
#define CTD_LIST_SIZE_MASK 0xffff
|
||||
#define CTD_LIST_SIZE_SHFT 0
|
||||
|
||||
/* event */
|
||||
#define CTD_EVENT_MASK 0x0f
|
||||
#define CTD_EVENT_SHFT 0
|
||||
|
||||
/* fid_ctl */
|
||||
#define CTD_FID2_MASK 0x03
|
||||
#define CTD_FID2_SHFT 4
|
||||
#define CTD_FID1_MASK 0x03
|
||||
#define CTD_FID1_SHFT 2
|
||||
#define CTD_FID0_MASK 0x03
|
||||
#define CTD_FID0_SHFT 0
|
||||
|
||||
/* type_source_ctl */
|
||||
#define CTD_PKT_TYPE_MASK 0x1f
|
||||
#define CTD_PKT_TYPE_SHFT 27
|
||||
#define CTD_SOURCE_MASK 0xff
|
||||
#define CTD_SOURCE_SHFT 16
|
||||
#define CTD_CONTROL_MASK 0x0f
|
||||
#define CTD_CONTROL_SHFT 0
|
||||
|
||||
static inline u32 ctd_pixel_line_count(int pixel_count, int line_count)
|
||||
{
|
||||
return (pixel_count << CTD_PIXEL_COUNT_SHFT) | line_count;
|
||||
}
|
||||
|
||||
static inline u32 ctd_set_fid_ctl(int fid0, int fid1, int fid2)
|
||||
{
|
||||
return (fid2 << CTD_FID2_SHFT) | (fid1 << CTD_FID1_SHFT) | fid0;
|
||||
}
|
||||
|
||||
static inline u32 ctd_type_source_ctl(int source, int control)
|
||||
{
|
||||
return (CTD_PKT_TYPE << CTD_PKT_TYPE_SHFT) |
|
||||
(source << CTD_SOURCE_SHFT) | control;
|
||||
}
|
||||
|
||||
static inline u32 ctd_get_pixel_count(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return ctd->pixel_line_count >> CTD_PIXEL_COUNT_SHFT;
|
||||
}
|
||||
|
||||
static inline int ctd_get_line_count(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return ctd->pixel_line_count & CTD_LINE_COUNT_MASK;
|
||||
}
|
||||
|
||||
static inline int ctd_get_event(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return ctd->event & CTD_EVENT_MASK;
|
||||
}
|
||||
|
||||
static inline int ctd_get_fid2_ctl(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return (ctd->fid_ctl >> CTD_FID2_SHFT) & CTD_FID2_MASK;
|
||||
}
|
||||
|
||||
static inline int ctd_get_fid1_ctl(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return (ctd->fid_ctl >> CTD_FID1_SHFT) & CTD_FID1_MASK;
|
||||
}
|
||||
|
||||
static inline int ctd_get_fid0_ctl(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return ctd->fid_ctl & CTD_FID2_MASK;
|
||||
}
|
||||
|
||||
static inline int ctd_get_pkt_type(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return ctd->type_source_ctl >> CTD_PKT_TYPE_SHFT;
|
||||
}
|
||||
|
||||
static inline int ctd_get_source(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return (ctd->type_source_ctl >> CTD_SOURCE_SHFT) & CTD_SOURCE_MASK;
|
||||
}
|
||||
|
||||
static inline int ctd_get_ctl(struct vpdma_ctd *ctd)
|
||||
{
|
||||
return ctd->type_source_ctl & CTD_CONTROL_MASK;
|
||||
}
|
||||
|
||||
#endif
|
2099
drivers/media/platform/ti-vpe/vpe.c
Normal file
2099
drivers/media/platform/ti-vpe/vpe.c
Normal file
File diff suppressed because it is too large
Load Diff
496
drivers/media/platform/ti-vpe/vpe_regs.h
Normal file
496
drivers/media/platform/ti-vpe/vpe_regs.h
Normal file
@ -0,0 +1,496 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Texas Instruments Inc.
|
||||
*
|
||||
* David Griego, <dagriego@biglakesoftware.com>
|
||||
* Dale Farnsworth, <dale@farnsworth.org>
|
||||
* Archit Taneja, <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __TI_VPE_REGS_H
|
||||
#define __TI_VPE_REGS_H
|
||||
|
||||
/* VPE register offsets and field selectors */
|
||||
|
||||
/* VPE top level regs */
|
||||
#define VPE_PID 0x0000
|
||||
#define VPE_PID_MINOR_MASK 0x3f
|
||||
#define VPE_PID_MINOR_SHIFT 0
|
||||
#define VPE_PID_CUSTOM_MASK 0x03
|
||||
#define VPE_PID_CUSTOM_SHIFT 6
|
||||
#define VPE_PID_MAJOR_MASK 0x07
|
||||
#define VPE_PID_MAJOR_SHIFT 8
|
||||
#define VPE_PID_RTL_MASK 0x1f
|
||||
#define VPE_PID_RTL_SHIFT 11
|
||||
#define VPE_PID_FUNC_MASK 0xfff
|
||||
#define VPE_PID_FUNC_SHIFT 16
|
||||
#define VPE_PID_SCHEME_MASK 0x03
|
||||
#define VPE_PID_SCHEME_SHIFT 30
|
||||
|
||||
#define VPE_SYSCONFIG 0x0010
|
||||
#define VPE_SYSCONFIG_IDLE_MASK 0x03
|
||||
#define VPE_SYSCONFIG_IDLE_SHIFT 2
|
||||
#define VPE_SYSCONFIG_STANDBY_MASK 0x03
|
||||
#define VPE_SYSCONFIG_STANDBY_SHIFT 4
|
||||
#define VPE_FORCE_IDLE_MODE 0
|
||||
#define VPE_NO_IDLE_MODE 1
|
||||
#define VPE_SMART_IDLE_MODE 2
|
||||
#define VPE_SMART_IDLE_WAKEUP_MODE 3
|
||||
#define VPE_FORCE_STANDBY_MODE 0
|
||||
#define VPE_NO_STANDBY_MODE 1
|
||||
#define VPE_SMART_STANDBY_MODE 2
|
||||
#define VPE_SMART_STANDBY_WAKEUP_MODE 3
|
||||
|
||||
#define VPE_INT0_STATUS0_RAW_SET 0x0020
|
||||
#define VPE_INT0_STATUS0_RAW VPE_INT0_STATUS0_RAW_SET
|
||||
#define VPE_INT0_STATUS0_CLR 0x0028
|
||||
#define VPE_INT0_STATUS0 VPE_INT0_STATUS0_CLR
|
||||
#define VPE_INT0_ENABLE0_SET 0x0030
|
||||
#define VPE_INT0_ENABLE0 VPE_INT0_ENABLE0_SET
|
||||
#define VPE_INT0_ENABLE0_CLR 0x0038
|
||||
#define VPE_INT0_LIST0_COMPLETE (1 << 0)
|
||||
#define VPE_INT0_LIST0_NOTIFY (1 << 1)
|
||||
#define VPE_INT0_LIST1_COMPLETE (1 << 2)
|
||||
#define VPE_INT0_LIST1_NOTIFY (1 << 3)
|
||||
#define VPE_INT0_LIST2_COMPLETE (1 << 4)
|
||||
#define VPE_INT0_LIST2_NOTIFY (1 << 5)
|
||||
#define VPE_INT0_LIST3_COMPLETE (1 << 6)
|
||||
#define VPE_INT0_LIST3_NOTIFY (1 << 7)
|
||||
#define VPE_INT0_LIST4_COMPLETE (1 << 8)
|
||||
#define VPE_INT0_LIST4_NOTIFY (1 << 9)
|
||||
#define VPE_INT0_LIST5_COMPLETE (1 << 10)
|
||||
#define VPE_INT0_LIST5_NOTIFY (1 << 11)
|
||||
#define VPE_INT0_LIST6_COMPLETE (1 << 12)
|
||||
#define VPE_INT0_LIST6_NOTIFY (1 << 13)
|
||||
#define VPE_INT0_LIST7_COMPLETE (1 << 14)
|
||||
#define VPE_INT0_LIST7_NOTIFY (1 << 15)
|
||||
#define VPE_INT0_DESCRIPTOR (1 << 16)
|
||||
#define VPE_DEI_FMD_INT (1 << 18)
|
||||
|
||||
#define VPE_INT0_STATUS1_RAW_SET 0x0024
|
||||
#define VPE_INT0_STATUS1_RAW VPE_INT0_STATUS1_RAW_SET
|
||||
#define VPE_INT0_STATUS1_CLR 0x002c
|
||||
#define VPE_INT0_STATUS1 VPE_INT0_STATUS1_CLR
|
||||
#define VPE_INT0_ENABLE1_SET 0x0034
|
||||
#define VPE_INT0_ENABLE1 VPE_INT0_ENABLE1_SET
|
||||
#define VPE_INT0_ENABLE1_CLR 0x003c
|
||||
#define VPE_INT0_CHANNEL_GROUP0 (1 << 0)
|
||||
#define VPE_INT0_CHANNEL_GROUP1 (1 << 1)
|
||||
#define VPE_INT0_CHANNEL_GROUP2 (1 << 2)
|
||||
#define VPE_INT0_CHANNEL_GROUP3 (1 << 3)
|
||||
#define VPE_INT0_CHANNEL_GROUP4 (1 << 4)
|
||||
#define VPE_INT0_CHANNEL_GROUP5 (1 << 5)
|
||||
#define VPE_INT0_CLIENT (1 << 7)
|
||||
#define VPE_DEI_ERROR_INT (1 << 16)
|
||||
#define VPE_DS1_UV_ERROR_INT (1 << 22)
|
||||
|
||||
#define VPE_INTC_EOI 0x00a0
|
||||
|
||||
#define VPE_CLK_ENABLE 0x0100
|
||||
#define VPE_VPEDMA_CLK_ENABLE (1 << 0)
|
||||
#define VPE_DATA_PATH_CLK_ENABLE (1 << 1)
|
||||
|
||||
#define VPE_CLK_RESET 0x0104
|
||||
#define VPE_VPDMA_CLK_RESET_MASK 0x1
|
||||
#define VPE_VPDMA_CLK_RESET_SHIFT 0
|
||||
#define VPE_DATA_PATH_CLK_RESET_MASK 0x1
|
||||
#define VPE_DATA_PATH_CLK_RESET_SHIFT 1
|
||||
#define VPE_MAIN_RESET_MASK 0x1
|
||||
#define VPE_MAIN_RESET_SHIFT 31
|
||||
|
||||
#define VPE_CLK_FORMAT_SELECT 0x010c
|
||||
#define VPE_CSC_SRC_SELECT_MASK 0x03
|
||||
#define VPE_CSC_SRC_SELECT_SHIFT 0
|
||||
#define VPE_RGB_OUT_SELECT (1 << 8)
|
||||
#define VPE_DS_SRC_SELECT_MASK 0x07
|
||||
#define VPE_DS_SRC_SELECT_SHIFT 9
|
||||
#define VPE_DS_BYPASS (1 << 16)
|
||||
#define VPE_COLOR_SEPARATE_422 (1 << 18)
|
||||
|
||||
#define VPE_DS_SRC_DEI_SCALER (5 << VPE_DS_SRC_SELECT_SHIFT)
|
||||
#define VPE_CSC_SRC_DEI_SCALER (3 << VPE_CSC_SRC_SELECT_SHIFT)
|
||||
|
||||
#define VPE_CLK_RANGE_MAP 0x011c
|
||||
#define VPE_RANGE_RANGE_MAP_Y_MASK 0x07
|
||||
#define VPE_RANGE_RANGE_MAP_Y_SHIFT 0
|
||||
#define VPE_RANGE_RANGE_MAP_UV_MASK 0x07
|
||||
#define VPE_RANGE_RANGE_MAP_UV_SHIFT 3
|
||||
#define VPE_RANGE_MAP_ON (1 << 6)
|
||||
#define VPE_RANGE_REDUCTION_ON (1 << 28)
|
||||
|
||||
/* VPE chrominance upsampler regs */
|
||||
#define VPE_US1_R0 0x0304
|
||||
#define VPE_US2_R0 0x0404
|
||||
#define VPE_US3_R0 0x0504
|
||||
#define VPE_US_C1_MASK 0x3fff
|
||||
#define VPE_US_C1_SHIFT 2
|
||||
#define VPE_US_C0_MASK 0x3fff
|
||||
#define VPE_US_C0_SHIFT 18
|
||||
#define VPE_US_MODE_MASK 0x03
|
||||
#define VPE_US_MODE_SHIFT 16
|
||||
#define VPE_ANCHOR_FID0_C1_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID0_C1_SHIFT 2
|
||||
#define VPE_ANCHOR_FID0_C0_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID0_C0_SHIFT 18
|
||||
|
||||
#define VPE_US1_R1 0x0308
|
||||
#define VPE_US2_R1 0x0408
|
||||
#define VPE_US3_R1 0x0508
|
||||
#define VPE_ANCHOR_FID0_C3_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID0_C3_SHIFT 2
|
||||
#define VPE_ANCHOR_FID0_C2_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID0_C2_SHIFT 18
|
||||
|
||||
#define VPE_US1_R2 0x030c
|
||||
#define VPE_US2_R2 0x040c
|
||||
#define VPE_US3_R2 0x050c
|
||||
#define VPE_INTERP_FID0_C1_MASK 0x3fff
|
||||
#define VPE_INTERP_FID0_C1_SHIFT 2
|
||||
#define VPE_INTERP_FID0_C0_MASK 0x3fff
|
||||
#define VPE_INTERP_FID0_C0_SHIFT 18
|
||||
|
||||
#define VPE_US1_R3 0x0310
|
||||
#define VPE_US2_R3 0x0410
|
||||
#define VPE_US3_R3 0x0510
|
||||
#define VPE_INTERP_FID0_C3_MASK 0x3fff
|
||||
#define VPE_INTERP_FID0_C3_SHIFT 2
|
||||
#define VPE_INTERP_FID0_C2_MASK 0x3fff
|
||||
#define VPE_INTERP_FID0_C2_SHIFT 18
|
||||
|
||||
#define VPE_US1_R4 0x0314
|
||||
#define VPE_US2_R4 0x0414
|
||||
#define VPE_US3_R4 0x0514
|
||||
#define VPE_ANCHOR_FID1_C1_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID1_C1_SHIFT 2
|
||||
#define VPE_ANCHOR_FID1_C0_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID1_C0_SHIFT 18
|
||||
|
||||
#define VPE_US1_R5 0x0318
|
||||
#define VPE_US2_R5 0x0418
|
||||
#define VPE_US3_R5 0x0518
|
||||
#define VPE_ANCHOR_FID1_C3_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID1_C3_SHIFT 2
|
||||
#define VPE_ANCHOR_FID1_C2_MASK 0x3fff
|
||||
#define VPE_ANCHOR_FID1_C2_SHIFT 18
|
||||
|
||||
#define VPE_US1_R6 0x031c
|
||||
#define VPE_US2_R6 0x041c
|
||||
#define VPE_US3_R6 0x051c
|
||||
#define VPE_INTERP_FID1_C1_MASK 0x3fff
|
||||
#define VPE_INTERP_FID1_C1_SHIFT 2
|
||||
#define VPE_INTERP_FID1_C0_MASK 0x3fff
|
||||
#define VPE_INTERP_FID1_C0_SHIFT 18
|
||||
|
||||
#define VPE_US1_R7 0x0320
|
||||
#define VPE_US2_R7 0x0420
|
||||
#define VPE_US3_R7 0x0520
|
||||
#define VPE_INTERP_FID0_C3_MASK 0x3fff
|
||||
#define VPE_INTERP_FID0_C3_SHIFT 2
|
||||
#define VPE_INTERP_FID0_C2_MASK 0x3fff
|
||||
#define VPE_INTERP_FID0_C2_SHIFT 18
|
||||
|
||||
/* VPE de-interlacer regs */
|
||||
#define VPE_DEI_FRAME_SIZE 0x0600
|
||||
#define VPE_DEI_WIDTH_MASK 0x07ff
|
||||
#define VPE_DEI_WIDTH_SHIFT 0
|
||||
#define VPE_DEI_HEIGHT_MASK 0x07ff
|
||||
#define VPE_DEI_HEIGHT_SHIFT 16
|
||||
#define VPE_DEI_INTERLACE_BYPASS (1 << 29)
|
||||
#define VPE_DEI_FIELD_FLUSH (1 << 30)
|
||||
#define VPE_DEI_PROGRESSIVE (1 << 31)
|
||||
|
||||
#define VPE_MDT_BYPASS 0x0604
|
||||
#define VPE_MDT_TEMPMAX_BYPASS (1 << 0)
|
||||
#define VPE_MDT_SPATMAX_BYPASS (1 << 1)
|
||||
|
||||
#define VPE_MDT_SF_THRESHOLD 0x0608
|
||||
#define VPE_MDT_SF_SC_THR1_MASK 0xff
|
||||
#define VPE_MDT_SF_SC_THR1_SHIFT 0
|
||||
#define VPE_MDT_SF_SC_THR2_MASK 0xff
|
||||
#define VPE_MDT_SF_SC_THR2_SHIFT 0
|
||||
#define VPE_MDT_SF_SC_THR3_MASK 0xff
|
||||
#define VPE_MDT_SF_SC_THR3_SHIFT 0
|
||||
|
||||
#define VPE_EDI_CONFIG 0x060c
|
||||
#define VPE_EDI_INP_MODE_MASK 0x03
|
||||
#define VPE_EDI_INP_MODE_SHIFT 0
|
||||
#define VPE_EDI_ENABLE_3D (1 << 2)
|
||||
#define VPE_EDI_ENABLE_CHROMA_3D (1 << 3)
|
||||
#define VPE_EDI_CHROMA3D_COR_THR_MASK 0xff
|
||||
#define VPE_EDI_CHROMA3D_COR_THR_SHIFT 8
|
||||
#define VPE_EDI_DIR_COR_LOWER_THR_MASK 0xff
|
||||
#define VPE_EDI_DIR_COR_LOWER_THR_SHIFT 16
|
||||
#define VPE_EDI_COR_SCALE_FACTOR_MASK 0xff
|
||||
#define VPE_EDI_COR_SCALE_FACTOR_SHIFT 23
|
||||
|
||||
#define VPE_DEI_EDI_LUT_R0 0x0610
|
||||
#define VPE_EDI_LUT0_MASK 0x1f
|
||||
#define VPE_EDI_LUT0_SHIFT 0
|
||||
#define VPE_EDI_LUT1_MASK 0x1f
|
||||
#define VPE_EDI_LUT1_SHIFT 8
|
||||
#define VPE_EDI_LUT2_MASK 0x1f
|
||||
#define VPE_EDI_LUT2_SHIFT 16
|
||||
#define VPE_EDI_LUT3_MASK 0x1f
|
||||
#define VPE_EDI_LUT3_SHIFT 24
|
||||
|
||||
#define VPE_DEI_EDI_LUT_R1 0x0614
|
||||
#define VPE_EDI_LUT0_MASK 0x1f
|
||||
#define VPE_EDI_LUT0_SHIFT 0
|
||||
#define VPE_EDI_LUT1_MASK 0x1f
|
||||
#define VPE_EDI_LUT1_SHIFT 8
|
||||
#define VPE_EDI_LUT2_MASK 0x1f
|
||||
#define VPE_EDI_LUT2_SHIFT 16
|
||||
#define VPE_EDI_LUT3_MASK 0x1f
|
||||
#define VPE_EDI_LUT3_SHIFT 24
|
||||
|
||||
#define VPE_DEI_EDI_LUT_R2 0x0618
|
||||
#define VPE_EDI_LUT4_MASK 0x1f
|
||||
#define VPE_EDI_LUT4_SHIFT 0
|
||||
#define VPE_EDI_LUT5_MASK 0x1f
|
||||
#define VPE_EDI_LUT5_SHIFT 8
|
||||
#define VPE_EDI_LUT6_MASK 0x1f
|
||||
#define VPE_EDI_LUT6_SHIFT 16
|
||||
#define VPE_EDI_LUT7_MASK 0x1f
|
||||
#define VPE_EDI_LUT7_SHIFT 24
|
||||
|
||||
#define VPE_DEI_EDI_LUT_R3 0x061c
|
||||
#define VPE_EDI_LUT8_MASK 0x1f
|
||||
#define VPE_EDI_LUT8_SHIFT 0
|
||||
#define VPE_EDI_LUT9_MASK 0x1f
|
||||
#define VPE_EDI_LUT9_SHIFT 8
|
||||
#define VPE_EDI_LUT10_MASK 0x1f
|
||||
#define VPE_EDI_LUT10_SHIFT 16
|
||||
#define VPE_EDI_LUT11_MASK 0x1f
|
||||
#define VPE_EDI_LUT11_SHIFT 24
|
||||
|
||||
#define VPE_DEI_FMD_WINDOW_R0 0x0620
|
||||
#define VPE_FMD_WINDOW_MINX_MASK 0x07ff
|
||||
#define VPE_FMD_WINDOW_MINX_SHIFT 0
|
||||
#define VPE_FMD_WINDOW_MAXX_MASK 0x07ff
|
||||
#define VPE_FMD_WINDOW_MAXX_SHIFT 16
|
||||
#define VPE_FMD_WINDOW_ENABLE (1 << 31)
|
||||
|
||||
#define VPE_DEI_FMD_WINDOW_R1 0x0624
|
||||
#define VPE_FMD_WINDOW_MINY_MASK 0x07ff
|
||||
#define VPE_FMD_WINDOW_MINY_SHIFT 0
|
||||
#define VPE_FMD_WINDOW_MAXY_MASK 0x07ff
|
||||
#define VPE_FMD_WINDOW_MAXY_SHIFT 16
|
||||
|
||||
#define VPE_DEI_FMD_CONTROL_R0 0x0628
|
||||
#define VPE_FMD_ENABLE (1 << 0)
|
||||
#define VPE_FMD_LOCK (1 << 1)
|
||||
#define VPE_FMD_JAM_DIR (1 << 2)
|
||||
#define VPE_FMD_BED_ENABLE (1 << 3)
|
||||
#define VPE_FMD_CAF_FIELD_THR_MASK 0xff
|
||||
#define VPE_FMD_CAF_FIELD_THR_SHIFT 16
|
||||
#define VPE_FMD_CAF_LINE_THR_MASK 0xff
|
||||
#define VPE_FMD_CAF_LINE_THR_SHIFT 24
|
||||
|
||||
#define VPE_DEI_FMD_CONTROL_R1 0x062c
|
||||
#define VPE_FMD_CAF_THR_MASK 0x000fffff
|
||||
#define VPE_FMD_CAF_THR_SHIFT 0
|
||||
|
||||
#define VPE_DEI_FMD_STATUS_R0 0x0630
|
||||
#define VPE_FMD_CAF_MASK 0x000fffff
|
||||
#define VPE_FMD_CAF_SHIFT 0
|
||||
#define VPE_FMD_RESET (1 << 24)
|
||||
|
||||
#define VPE_DEI_FMD_STATUS_R1 0x0634
|
||||
#define VPE_FMD_FIELD_DIFF_MASK 0x0fffffff
|
||||
#define VPE_FMD_FIELD_DIFF_SHIFT 0
|
||||
|
||||
#define VPE_DEI_FMD_STATUS_R2 0x0638
|
||||
#define VPE_FMD_FRAME_DIFF_MASK 0x000fffff
|
||||
#define VPE_FMD_FRAME_DIFF_SHIFT 0
|
||||
|
||||
/* VPE scaler regs */
|
||||
#define VPE_SC_MP_SC0 0x0700
|
||||
#define VPE_INTERLACE_O (1 << 0)
|
||||
#define VPE_LINEAR (1 << 1)
|
||||
#define VPE_SC_BYPASS (1 << 2)
|
||||
#define VPE_INVT_FID (1 << 3)
|
||||
#define VPE_USE_RAV (1 << 4)
|
||||
#define VPE_ENABLE_EV (1 << 5)
|
||||
#define VPE_AUTO_HS (1 << 6)
|
||||
#define VPE_DCM_2X (1 << 7)
|
||||
#define VPE_DCM_4X (1 << 8)
|
||||
#define VPE_HP_BYPASS (1 << 9)
|
||||
#define VPE_INTERLACE_I (1 << 10)
|
||||
#define VPE_ENABLE_SIN2_VER_INTP (1 << 11)
|
||||
#define VPE_Y_PK_EN (1 << 14)
|
||||
#define VPE_TRIM (1 << 15)
|
||||
#define VPE_SELFGEN_FID (1 << 16)
|
||||
|
||||
#define VPE_SC_MP_SC1 0x0704
|
||||
#define VPE_ROW_ACC_INC_MASK 0x07ffffff
|
||||
#define VPE_ROW_ACC_INC_SHIFT 0
|
||||
|
||||
#define VPE_SC_MP_SC2 0x0708
|
||||
#define VPE_ROW_ACC_OFFSET_MASK 0x0fffffff
|
||||
#define VPE_ROW_ACC_OFFSET_SHIFT 0
|
||||
|
||||
#define VPE_SC_MP_SC3 0x070c
|
||||
#define VPE_ROW_ACC_OFFSET_B_MASK 0x0fffffff
|
||||
#define VPE_ROW_ACC_OFFSET_B_SHIFT 0
|
||||
|
||||
#define VPE_SC_MP_SC4 0x0710
|
||||
#define VPE_TAR_H_MASK 0x07ff
|
||||
#define VPE_TAR_H_SHIFT 0
|
||||
#define VPE_TAR_W_MASK 0x07ff
|
||||
#define VPE_TAR_W_SHIFT 12
|
||||
#define VPE_LIN_ACC_INC_U_MASK 0x07
|
||||
#define VPE_LIN_ACC_INC_U_SHIFT 24
|
||||
#define VPE_NLIN_ACC_INIT_U_MASK 0x07
|
||||
#define VPE_NLIN_ACC_INIT_U_SHIFT 28
|
||||
|
||||
#define VPE_SC_MP_SC5 0x0714
|
||||
#define VPE_SRC_H_MASK 0x07ff
|
||||
#define VPE_SRC_H_SHIFT 0
|
||||
#define VPE_SRC_W_MASK 0x07ff
|
||||
#define VPE_SRC_W_SHIFT 12
|
||||
#define VPE_NLIN_ACC_INC_U_MASK 0x07
|
||||
#define VPE_NLIN_ACC_INC_U_SHIFT 24
|
||||
|
||||
#define VPE_SC_MP_SC6 0x0718
|
||||
#define VPE_ROW_ACC_INIT_RAV_MASK 0x03ff
|
||||
#define VPE_ROW_ACC_INIT_RAV_SHIFT 0
|
||||
#define VPE_ROW_ACC_INIT_RAV_B_MASK 0x03ff
|
||||
#define VPE_ROW_ACC_INIT_RAV_B_SHIFT 10
|
||||
|
||||
#define VPE_SC_MP_SC8 0x0720
|
||||
#define VPE_NLIN_LEFT_MASK 0x07ff
|
||||
#define VPE_NLIN_LEFT_SHIFT 0
|
||||
#define VPE_NLIN_RIGHT_MASK 0x07ff
|
||||
#define VPE_NLIN_RIGHT_SHIFT 12
|
||||
|
||||
#define VPE_SC_MP_SC9 0x0724
|
||||
#define VPE_LIN_ACC_INC VPE_SC_MP_SC9
|
||||
|
||||
#define VPE_SC_MP_SC10 0x0728
|
||||
#define VPE_NLIN_ACC_INIT VPE_SC_MP_SC10
|
||||
|
||||
#define VPE_SC_MP_SC11 0x072c
|
||||
#define VPE_NLIN_ACC_INC VPE_SC_MP_SC11
|
||||
|
||||
#define VPE_SC_MP_SC12 0x0730
|
||||
#define VPE_COL_ACC_OFFSET_MASK 0x01ffffff
|
||||
#define VPE_COL_ACC_OFFSET_SHIFT 0
|
||||
|
||||
#define VPE_SC_MP_SC13 0x0734
|
||||
#define VPE_SC_FACTOR_RAV_MASK 0x03ff
|
||||
#define VPE_SC_FACTOR_RAV_SHIFT 0
|
||||
#define VPE_CHROMA_INTP_THR_MASK 0x03ff
|
||||
#define VPE_CHROMA_INTP_THR_SHIFT 12
|
||||
#define VPE_DELTA_CHROMA_THR_MASK 0x0f
|
||||
#define VPE_DELTA_CHROMA_THR_SHIFT 24
|
||||
|
||||
#define VPE_SC_MP_SC17 0x0744
|
||||
#define VPE_EV_THR_MASK 0x03ff
|
||||
#define VPE_EV_THR_SHIFT 12
|
||||
#define VPE_DELTA_LUMA_THR_MASK 0x0f
|
||||
#define VPE_DELTA_LUMA_THR_SHIFT 24
|
||||
#define VPE_DELTA_EV_THR_MASK 0x0f
|
||||
#define VPE_DELTA_EV_THR_SHIFT 28
|
||||
|
||||
#define VPE_SC_MP_SC18 0x0748
|
||||
#define VPE_HS_FACTOR_MASK 0x03ff
|
||||
#define VPE_HS_FACTOR_SHIFT 0
|
||||
#define VPE_CONF_DEFAULT_MASK 0x01ff
|
||||
#define VPE_CONF_DEFAULT_SHIFT 16
|
||||
|
||||
#define VPE_SC_MP_SC19 0x074c
|
||||
#define VPE_HPF_COEFF0_MASK 0xff
|
||||
#define VPE_HPF_COEFF0_SHIFT 0
|
||||
#define VPE_HPF_COEFF1_MASK 0xff
|
||||
#define VPE_HPF_COEFF1_SHIFT 8
|
||||
#define VPE_HPF_COEFF2_MASK 0xff
|
||||
#define VPE_HPF_COEFF2_SHIFT 16
|
||||
#define VPE_HPF_COEFF3_MASK 0xff
|
||||
#define VPE_HPF_COEFF3_SHIFT 23
|
||||
|
||||
#define VPE_SC_MP_SC20 0x0750
|
||||
#define VPE_HPF_COEFF4_MASK 0xff
|
||||
#define VPE_HPF_COEFF4_SHIFT 0
|
||||
#define VPE_HPF_COEFF5_MASK 0xff
|
||||
#define VPE_HPF_COEFF5_SHIFT 8
|
||||
#define VPE_HPF_NORM_SHIFT_MASK 0x07
|
||||
#define VPE_HPF_NORM_SHIFT_SHIFT 16
|
||||
#define VPE_NL_LIMIT_MASK 0x1ff
|
||||
#define VPE_NL_LIMIT_SHIFT 20
|
||||
|
||||
#define VPE_SC_MP_SC21 0x0754
|
||||
#define VPE_NL_LO_THR_MASK 0x01ff
|
||||
#define VPE_NL_LO_THR_SHIFT 0
|
||||
#define VPE_NL_LO_SLOPE_MASK 0xff
|
||||
#define VPE_NL_LO_SLOPE_SHIFT 16
|
||||
|
||||
#define VPE_SC_MP_SC22 0x0758
|
||||
#define VPE_NL_HI_THR_MASK 0x01ff
|
||||
#define VPE_NL_HI_THR_SHIFT 0
|
||||
#define VPE_NL_HI_SLOPE_SH_MASK 0x07
|
||||
#define VPE_NL_HI_SLOPE_SH_SHIFT 16
|
||||
|
||||
#define VPE_SC_MP_SC23 0x075c
|
||||
#define VPE_GRADIENT_THR_MASK 0x07ff
|
||||
#define VPE_GRADIENT_THR_SHIFT 0
|
||||
#define VPE_GRADIENT_THR_RANGE_MASK 0x0f
|
||||
#define VPE_GRADIENT_THR_RANGE_SHIFT 12
|
||||
#define VPE_MIN_GY_THR_MASK 0xff
|
||||
#define VPE_MIN_GY_THR_SHIFT 16
|
||||
#define VPE_MIN_GY_THR_RANGE_MASK 0x0f
|
||||
#define VPE_MIN_GY_THR_RANGE_SHIFT 28
|
||||
|
||||
#define VPE_SC_MP_SC24 0x0760
|
||||
#define VPE_ORG_H_MASK 0x07ff
|
||||
#define VPE_ORG_H_SHIFT 0
|
||||
#define VPE_ORG_W_MASK 0x07ff
|
||||
#define VPE_ORG_W_SHIFT 16
|
||||
|
||||
#define VPE_SC_MP_SC25 0x0764
|
||||
#define VPE_OFF_H_MASK 0x07ff
|
||||
#define VPE_OFF_H_SHIFT 0
|
||||
#define VPE_OFF_W_MASK 0x07ff
|
||||
#define VPE_OFF_W_SHIFT 16
|
||||
|
||||
/* VPE color space converter regs */
|
||||
#define VPE_CSC_CSC00 0x5700
|
||||
#define VPE_CSC_A0_MASK 0x1fff
|
||||
#define VPE_CSC_A0_SHIFT 0
|
||||
#define VPE_CSC_B0_MASK 0x1fff
|
||||
#define VPE_CSC_B0_SHIFT 16
|
||||
|
||||
#define VPE_CSC_CSC01 0x5704
|
||||
#define VPE_CSC_C0_MASK 0x1fff
|
||||
#define VPE_CSC_C0_SHIFT 0
|
||||
#define VPE_CSC_A1_MASK 0x1fff
|
||||
#define VPE_CSC_A1_SHIFT 16
|
||||
|
||||
#define VPE_CSC_CSC02 0x5708
|
||||
#define VPE_CSC_B1_MASK 0x1fff
|
||||
#define VPE_CSC_B1_SHIFT 0
|
||||
#define VPE_CSC_C1_MASK 0x1fff
|
||||
#define VPE_CSC_C1_SHIFT 16
|
||||
|
||||
#define VPE_CSC_CSC03 0x570c
|
||||
#define VPE_CSC_A2_MASK 0x1fff
|
||||
#define VPE_CSC_A2_SHIFT 0
|
||||
#define VPE_CSC_B2_MASK 0x1fff
|
||||
#define VPE_CSC_B2_SHIFT 16
|
||||
|
||||
#define VPE_CSC_CSC04 0x5710
|
||||
#define VPE_CSC_C2_MASK 0x1fff
|
||||
#define VPE_CSC_C2_SHIFT 0
|
||||
#define VPE_CSC_D0_MASK 0x0fff
|
||||
#define VPE_CSC_D0_SHIFT 16
|
||||
|
||||
#define VPE_CSC_CSC05 0x5714
|
||||
#define VPE_CSC_D1_MASK 0x0fff
|
||||
#define VPE_CSC_D1_SHIFT 0
|
||||
#define VPE_CSC_D2_MASK 0x0fff
|
||||
#define VPE_CSC_D2_SHIFT 16
|
||||
#define VPE_CSC_BYPASS (1 << 28)
|
||||
|
||||
#endif
|
@ -403,7 +403,7 @@ static int timblogiw_s_input(struct file *file, void *priv, unsigned int input)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timblogiw_streamon(struct file *file, void *priv, unsigned int type)
|
||||
static int timblogiw_streamon(struct file *file, void *priv, enum v4l2_buf_type type)
|
||||
{
|
||||
struct video_device *vdev = video_devdata(file);
|
||||
struct timblogiw_fh *fh = priv;
|
||||
@ -420,7 +420,7 @@ static int timblogiw_streamon(struct file *file, void *priv, unsigned int type)
|
||||
}
|
||||
|
||||
static int timblogiw_streamoff(struct file *file, void *priv,
|
||||
unsigned int type)
|
||||
enum v4l2_buf_type type)
|
||||
{
|
||||
struct video_device *vdev = video_devdata(file);
|
||||
struct timblogiw_fh *fh = priv;
|
||||
|
@ -123,7 +123,7 @@ static int keene_cmd_set(struct keene_device *radio)
|
||||
/* If bit 0 is set, then transmit mono, otherwise stereo.
|
||||
If bit 2 is set, then enable 75 us preemphasis, otherwise
|
||||
it is 50 us. */
|
||||
radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0);
|
||||
radio->buffer[3] = (radio->stereo ? 0 : 1) | (radio->preemph_75_us ? 4 : 0);
|
||||
radio->buffer[4] = 0x00;
|
||||
radio->buffer[5] = 0x00;
|
||||
radio->buffer[6] = 0x00;
|
||||
|
@ -74,8 +74,8 @@ static u8 fmr2_tea575x_get_pins(struct snd_tea575x *tea)
|
||||
struct fmr2 *fmr2 = tea->private_data;
|
||||
u8 bits = inb(fmr2->io);
|
||||
|
||||
return (bits & STR_DATA) ? TEA575X_DATA : 0 |
|
||||
(bits & STR_MOST) ? TEA575X_MOST : 0;
|
||||
return ((bits & STR_DATA) ? TEA575X_DATA : 0) |
|
||||
((bits & STR_MOST) ? TEA575X_MOST : 0);
|
||||
}
|
||||
|
||||
static void fmr2_tea575x_set_direction(struct snd_tea575x *tea, bool output)
|
||||
@ -295,7 +295,6 @@ static void fmr2_remove(struct fmr2 *fmr2)
|
||||
static int fmr2_isa_remove(struct device *pdev, unsigned int ndev)
|
||||
{
|
||||
fmr2_remove(dev_get_drvdata(pdev));
|
||||
dev_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ static unsigned int si470x_get_step(struct si470x_device *radio)
|
||||
/* 2: 50 kHz */
|
||||
default:
|
||||
return 50 * 16;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1456,7 +1456,7 @@ static int si4713_probe(struct i2c_client *client,
|
||||
|
||||
if (client->irq) {
|
||||
rval = request_irq(client->irq,
|
||||
si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
|
||||
si4713_handler, IRQF_TRIGGER_FALLING,
|
||||
client->name, sdev);
|
||||
if (rval < 0) {
|
||||
v4l2_err(&sdev->sd, "Could not request IRQ\n");
|
||||
|
@ -175,7 +175,7 @@ static int_handler_prototype int_handler_table[] = {
|
||||
fm_irq_handle_intmsk_cmd_resp
|
||||
};
|
||||
|
||||
long (*g_st_write) (struct sk_buff *skb);
|
||||
static long (*g_st_write) (struct sk_buff *skb);
|
||||
static struct completion wait_for_fmdrv_reg_comp;
|
||||
|
||||
static inline void fm_irq_call(struct fmdev *fmdev)
|
||||
|
@ -322,4 +322,14 @@ config IR_GPIO_CIR
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called gpio-ir-recv.
|
||||
|
||||
config RC_ST
|
||||
tristate "ST remote control receiver"
|
||||
depends on ARCH_STI && RC_CORE
|
||||
help
|
||||
Say Y here if you want support for ST remote control driver
|
||||
which allows both IR and UHF RX.
|
||||
The driver passes raw pulse and space information to the LIRC decoder.
|
||||
|
||||
If you're not sure, select N here.
|
||||
|
||||
endif #RC_DEVICES
|
||||
|
@ -30,3 +30,4 @@ obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
|
||||
obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
|
||||
obj-$(CONFIG_IR_IGUANA) += iguanair.o
|
||||
obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
|
||||
obj-$(CONFIG_RC_ST) += st_rc.o
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.h>
|
||||
|
@ -201,8 +201,7 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
|
||||
|
||||
lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
|
||||
retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
|
||||
IRQF_DISABLED | IRQF_SHARED,
|
||||
"lirc_pulse_timer", lirc_rx51);
|
||||
IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
|
||||
if (retval) {
|
||||
dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
|
||||
goto err2;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user