OpenCloudOS-Kernel/drivers/media/pci/solo6x10/solo6x10-enc.c

332 lines
8.8 KiB
C
Raw Normal View History

treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157 Based on 3 normalized pattern(s): 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 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 [author] [kishon] [vijay] [abraham] [i] [kishon]@[ti] [com] 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 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 [author] [graeme] [gregory] [gg]@[slimlogic] [co] [uk] [author] [kishon] [vijay] [abraham] [i] [kishon]@[ti] [com] [based] [on] [twl6030]_[usb] [c] [author] [hema] [hk] [hemahk]@[ti] [com] 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 extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 1105 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Richard Fontana <rfontana@redhat.com> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070033.202006027@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-27 14:55:06 +08:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
*
* Original author:
* Ben Collins <bcollins@ubuntu.com>
*
* Additional work by:
* John Brooks <john.brooks@bluecherry.net>
*/
#include <linux/kernel.h>
#include <linux/font.h>
#include <linux/bitrev.h>
#include <linux/slab.h>
#include "solo6x10.h"
#define VI_PROG_HSIZE (1280 - 16)
#define VI_PROG_VSIZE (1024 - 16)
#define IRQ_LEVEL 2
static void solo_capture_config(struct solo_dev *solo_dev)
{
unsigned long height;
unsigned long width;
void *buf;
int i;
solo_reg_write(solo_dev, SOLO_CAP_BASE,
SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
- SOLO_CAP_PAGE_SIZE) >> 16)
| SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
/* XXX: Undocumented bits at b17 and b24 */
if (solo_dev->type == SOLO_DEV_6110) {
/* NOTE: Ref driver has (62 << 24) here as well, but it causes
* wacked out frame timing on 4-port 6110. */
solo_reg_write(solo_dev, SOLO_CAP_BTW,
(1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
SOLO_CAP_MAX_BANDWIDTH(36));
} else {
solo_reg_write(solo_dev, SOLO_CAP_BTW,
(1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
SOLO_CAP_MAX_BANDWIDTH(32));
}
/* Set scale 1, 9 dimension */
width = solo_dev->video_hsize;
height = solo_dev->video_vsize;
solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 2, 10 dimension */
width = solo_dev->video_hsize / 2;
height = solo_dev->video_vsize;
solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 3, 11 dimension */
width = solo_dev->video_hsize / 2;
height = solo_dev->video_vsize / 2;
solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 4, 12 dimension */
width = solo_dev->video_hsize / 3;
height = solo_dev->video_vsize / 3;
solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 5, 13 dimension */
width = solo_dev->video_hsize / 4;
height = solo_dev->video_vsize / 2;
solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Progressive */
width = VI_PROG_HSIZE;
height = VI_PROG_VSIZE;
solo_reg_write(solo_dev, SOLO_DIM_PROG,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Clear OSD */
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
0xF0 << 16 | 0x80 << 8 | 0x80);
if (solo_dev->type == SOLO_DEV_6010)
solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
else
solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
| SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
/* Clear OSG buffer */
buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
if (!buf)
return;
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_p2m_dma(solo_dev, 1, buf,
SOLO_EOSD_EXT_ADDR +
(SOLO_EOSD_EXT_SIZE(solo_dev) * i),
SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
}
kfree(buf);
}
#define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
/* Should be called with enable_lock held */
int solo_osd_print(struct solo_enc_dev *solo_enc)
{
struct solo_dev *solo_dev = solo_enc->solo_dev;
u8 *str = solo_enc->osd_text;
u8 *buf = solo_enc->osd_buf;
u32 reg;
const struct font_desc *vga = find_font("VGA8x16");
const u8 *vga_data;
int i, j;
if (WARN_ON_ONCE(!vga))
return -ENODEV;
reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
if (!*str) {
/* Disable OSD on this channel */
reg &= ~(1 << solo_enc->ch);
goto out;
}
memset(buf, 0, SOLO_OSD_WRITE_SIZE);
vga_data = (const u8 *)vga->data;
for (i = 0; *str; i++, str++) {
for (j = 0; j < 16; j++) {
buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
bitrev8(vga_data[(*str << 4) | j]);
}
}
solo_p2m_dma(solo_dev, 1, buf,
SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
SOLO_OSD_WRITE_SIZE, 0, 0);
/* Enable OSD on this channel */
reg |= (1 << solo_enc->ch);
out:
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
return 0;
}
media: drivers: remove "/**" from non-kernel-doc comments Several comments are wrongly tagged as kernel-doc, causing those warnings: drivers/media/rc/st_rc.c:98: warning: No description found for parameter 'irq' drivers/media/rc/st_rc.c:98: warning: No description found for parameter 'data' drivers/media/pci/solo6x10/solo6x10-enc.c:183: warning: No description found for parameter 'solo_dev' drivers/media/pci/solo6x10/solo6x10-enc.c:183: warning: No description found for parameter 'ch' drivers/media/pci/solo6x10/solo6x10-enc.c:183: warning: No description found for parameter 'qp' drivers/media/usb/pwc/pwc-dec23.c:652: warning: Cannot understand * on line 652 - I thought it was a doc line drivers/media/usb/dvb-usb/cinergyT2-fe.c:40: warning: No description found for parameter 'op' drivers/media/usb/dvb-usb/friio-fe.c:301: warning: Cannot understand * (reg, val) commad list to initialize this module. on line 301 - I thought it was a doc line drivers/media/rc/streamzap.c:201: warning: No description found for parameter 'urb' drivers/media/rc/streamzap.c:333: warning: No description found for parameter 'intf' drivers/media/rc/streamzap.c:333: warning: No description found for parameter 'id' drivers/media/rc/streamzap.c:464: warning: No description found for parameter 'interface' drivers/media/i2c/ov5647.c:432: warning: Cannot understand * @short Subdev core operations registration on line 432 - I thought it was a doc line drivers/media/usb/dvb-usb/friio.c:35: warning: No description found for parameter 'd' drivers/media/usb/dvb-usb/friio.c:35: warning: No description found for parameter 'addr' drivers/media/usb/dvb-usb/friio.c:35: warning: No description found for parameter 'wbuf' drivers/media/usb/dvb-usb/friio.c:35: warning: No description found for parameter 'wlen' drivers/media/usb/dvb-usb/friio.c:35: warning: No description found for parameter 'rbuf' drivers/media/usb/dvb-usb/friio.c:35: warning: No description found for parameter 'rlen' drivers/media/platform/vim2m.c:350: warning: No description found for parameter 'priv' drivers/media/dvb-frontends/tua6100.c:34: warning: cannot understand function prototype: 'struct tua6100_priv ' drivers/media/platform/sti/hva/hva-h264.c:140: warning: cannot understand function prototype: 'struct hva_h264_stereo_video_sei ' drivers/media/platform/sti/hva/hva-h264.c:150: warning: Cannot understand * @frame_width: width in pixels of the buffer containing the input frame on line 150 - I thought it was a doc line drivers/media/platform/sti/hva/hva-h264.c:356: warning: Cannot understand * @ slice_size: slice size on line 356 - I thought it was a doc line drivers/media/platform/sti/hva/hva-h264.c:369: warning: Cannot understand * @ bitstream_size: bitstream size on line 369 - I thought it was a doc line drivers/media/platform/sti/hva/hva-h264.c:395: warning: Cannot understand * @seq_info: sequence information buffer on line 395 - I thought it was a doc line drivers/media/dvb-frontends/sp887x.c:137: warning: No description found for parameter 'fe' drivers/media/dvb-frontends/sp887x.c:137: warning: No description found for parameter 'fw' drivers/media/dvb-frontends/sp887x.c:287: warning: No description found for parameter 'n' drivers/media/dvb-frontends/sp887x.c:287: warning: No description found for parameter 'd' drivers/media/dvb-frontends/sp887x.c:287: warning: No description found for parameter 'quotient_i' drivers/media/dvb-frontends/sp887x.c:287: warning: No description found for parameter 'quotient_f' drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c:83: warning: cannot understand function prototype: 'struct ttusb ' drivers/media/platform/sh_veu.c:277: warning: No description found for parameter 'priv' drivers/media/dvb-frontends/zl10036.c:33: warning: cannot understand function prototype: 'int zl10036_debug; ' drivers/media/dvb-frontends/zl10036.c:179: warning: No description found for parameter 'state' drivers/media/dvb-frontends/zl10036.c:179: warning: No description found for parameter 'frequency' drivers/media/platform/rcar_fdp1.c:1139: warning: No description found for parameter 'priv' drivers/media/platform/ti-vpe/vpe.c:933: warning: No description found for parameter 'priv' drivers/media/usb/gspca/ov519.c:36: warning: No description found for parameter 'fmt' drivers/media/usb/dvb-usb/dib0700_devices.c:3367: warning: No description found for parameter 'adap' Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-11-29 21:33:45 +08:00
/*
* Set channel Quality Profile (0-3).
*/
void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
unsigned int qp)
{
unsigned long flags;
unsigned int idx, reg;
if ((ch > 31) || (qp > 3))
return;
if (solo_dev->type == SOLO_DEV_6010)
return;
if (ch < 16) {
idx = 0;
reg = SOLO_VE_JPEG_QP_CH_L;
} else {
ch -= 16;
idx = 1;
reg = SOLO_VE_JPEG_QP_CH_H;
}
ch *= 2;
spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
solo_dev->jpeg_qp[idx] &= ~(3 << ch);
solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
}
int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
{
int idx;
if (solo_dev->type == SOLO_DEV_6010)
return 2;
if (WARN_ON_ONCE(ch > 31))
return 2;
if (ch < 16) {
idx = 0;
} else {
ch -= 16;
idx = 1;
}
ch *= 2;
return (solo_dev->jpeg_qp[idx] >> ch) & 3;
}
#define SOLO_QP_INIT 0xaaaaaaaa
static void solo_jpeg_config(struct solo_dev *solo_dev)
{
if (solo_dev->type == SOLO_DEV_6010) {
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
(2 << 24) | (2 << 16) | (2 << 8) | 2);
} else {
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
(4 << 24) | (3 << 16) | (2 << 8) | 1);
}
spin_lock_init(&solo_dev->jpeg_qp_lock);
/* Initialize Quality Profile for all channels */
solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
if (solo_dev->type == SOLO_DEV_6110) {
solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
(0 << 16) | (30 << 8) | 60);
}
}
static void solo_mp4e_config(struct solo_dev *solo_dev)
{
int i;
u32 cfg;
solo_reg_write(solo_dev, SOLO_VE_CFG0,
SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
| SOLO_VE_MOTION_MODE(0);
if (solo_dev->type != SOLO_DEV_6010) {
cfg |= SOLO_VE_MPEG_SIZE_H(
(SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
cfg |= SOLO_VE_JPEG_SIZE_H(
(SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
}
solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
if (solo_dev->type == SOLO_DEV_6110)
solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
solo_reg_write(solo_dev, SOLO_VE_ATTR,
SOLO_VE_LITTLE_ENDIAN |
SOLO_COMP_ATTR_FCODE(1) |
SOLO_COMP_TIME_INC(0) |
SOLO_COMP_TIME_WIDTH(15) |
SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
(SOLO_EREF_EXT_ADDR(solo_dev) +
(i * SOLO_EREF_EXT_SIZE)) >> 16);
solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
(SOLO_EREF_EXT_ADDR(solo_dev) +
((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
}
if (solo_dev->type == SOLO_DEV_6110) {
solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
} else {
for (i = 0; i < solo_dev->nr_chans; i++)
solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
}
}
int solo_enc_init(struct solo_dev *solo_dev)
{
int i;
solo_capture_config(solo_dev);
solo_mp4e_config(solo_dev);
solo_jpeg_config(solo_dev);
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
}
return 0;
}
void solo_enc_exit(struct solo_dev *solo_dev)
{
int i;
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
}
}