^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Original author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Ben Collins <bcollins@ubuntu.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Additional work by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * John Brooks <john.brooks@bluecherry.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/font.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/bitrev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "solo6x10.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define VI_PROG_HSIZE (1280 - 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define VI_PROG_VSIZE (1024 - 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define IRQ_LEVEL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void solo_capture_config(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) solo_reg_write(solo_dev, SOLO_CAP_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) - SOLO_CAP_PAGE_SIZE) >> 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* XXX: Undocumented bits at b17 and b24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (solo_dev->type == SOLO_DEV_6110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* NOTE: Ref driver has (62 << 24) here as well, but it causes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * wacked out frame timing on 4-port 6110. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) solo_reg_write(solo_dev, SOLO_CAP_BTW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) SOLO_CAP_MAX_BANDWIDTH(36));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) solo_reg_write(solo_dev, SOLO_CAP_BTW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) SOLO_CAP_MAX_BANDWIDTH(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Set scale 1, 9 dimension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) width = solo_dev->video_hsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) height = solo_dev->video_vsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) SOLO_DIM_H_MB_NUM(width / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) SOLO_DIM_V_MB_NUM_FIELD(height / 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Set scale 2, 10 dimension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) width = solo_dev->video_hsize / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) height = solo_dev->video_vsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) SOLO_DIM_H_MB_NUM(width / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) SOLO_DIM_V_MB_NUM_FIELD(height / 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Set scale 3, 11 dimension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) width = solo_dev->video_hsize / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) height = solo_dev->video_vsize / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) SOLO_DIM_H_MB_NUM(width / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) SOLO_DIM_V_MB_NUM_FIELD(height / 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Set scale 4, 12 dimension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) width = solo_dev->video_hsize / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) height = solo_dev->video_vsize / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) SOLO_DIM_H_MB_NUM(width / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) SOLO_DIM_V_MB_NUM_FIELD(height / 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Set scale 5, 13 dimension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) width = solo_dev->video_hsize / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) height = solo_dev->video_vsize / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) SOLO_DIM_H_MB_NUM(width / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) SOLO_DIM_V_MB_NUM_FIELD(height / 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Progressive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) width = VI_PROG_HSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) height = VI_PROG_VSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) solo_reg_write(solo_dev, SOLO_DIM_PROG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) SOLO_DIM_H_MB_NUM(width / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) SOLO_DIM_V_MB_NUM_FIELD(height / 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Clear OSD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 0xF0 << 16 | 0x80 << 8 | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (solo_dev->type == SOLO_DEV_6010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* Clear OSG buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) for (i = 0; i < solo_dev->nr_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) solo_p2m_dma(solo_dev, 1, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) SOLO_EOSD_EXT_ADDR +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) (SOLO_EOSD_EXT_SIZE(solo_dev) * i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Should be called with enable_lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int solo_osd_print(struct solo_enc_dev *solo_enc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct solo_dev *solo_dev = solo_enc->solo_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u8 *str = solo_enc->osd_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u8 *buf = solo_enc->osd_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) const struct font_desc *vga = find_font("VGA8x16");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) const u8 *vga_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (WARN_ON_ONCE(!vga))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (!*str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Disable OSD on this channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) reg &= ~(1 << solo_enc->ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) memset(buf, 0, SOLO_OSD_WRITE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) vga_data = (const u8 *)vga->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) for (i = 0; *str; i++, str++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) for (j = 0; j < 16; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bitrev8(vga_data[(*str << 4) | j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) solo_p2m_dma(solo_dev, 1, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) SOLO_OSD_WRITE_SIZE, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Enable OSD on this channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) reg |= (1 << solo_enc->ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Set channel Quality Profile (0-3).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int qp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned int idx, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if ((ch > 31) || (qp > 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (solo_dev->type == SOLO_DEV_6010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (ch < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) reg = SOLO_VE_JPEG_QP_CH_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ch -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) reg = SOLO_VE_JPEG_QP_CH_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ch *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) solo_dev->jpeg_qp[idx] &= ~(3 << ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (solo_dev->type == SOLO_DEV_6010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (WARN_ON_ONCE(ch > 31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (ch < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ch -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ch *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return (solo_dev->jpeg_qp[idx] >> ch) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define SOLO_QP_INIT 0xaaaaaaaa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static void solo_jpeg_config(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (solo_dev->type == SOLO_DEV_6010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) (2 << 24) | (2 << 16) | (2 << 8) | 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) (4 << 24) | (3 << 16) | (2 << 8) | 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) spin_lock_init(&solo_dev->jpeg_qp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Initialize Quality Profile for all channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) (SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (solo_dev->type == SOLO_DEV_6110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) (0 << 16) | (30 << 8) | 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void solo_mp4e_config(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) solo_reg_write(solo_dev, SOLO_VE_CFG0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) | SOLO_VE_MOTION_MODE(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (solo_dev->type != SOLO_DEV_6010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) cfg |= SOLO_VE_MPEG_SIZE_H(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) (SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) cfg |= SOLO_VE_JPEG_SIZE_H(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) (SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (solo_dev->type == SOLO_DEV_6110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) solo_reg_write(solo_dev, SOLO_VE_ATTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) SOLO_VE_LITTLE_ENDIAN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) SOLO_COMP_ATTR_FCODE(1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) SOLO_COMP_TIME_INC(0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) SOLO_COMP_TIME_WIDTH(15) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) for (i = 0; i < solo_dev->nr_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) (SOLO_EREF_EXT_ADDR(solo_dev) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) (i * SOLO_EREF_EXT_SIZE)) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) (SOLO_EREF_EXT_ADDR(solo_dev) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (solo_dev->type == SOLO_DEV_6110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (i = 0; i < solo_dev->nr_chans; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int solo_enc_init(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) solo_capture_config(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) solo_mp4e_config(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) solo_jpeg_config(solo_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) for (i = 0; i < solo_dev->nr_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) void solo_enc_exit(struct solo_dev *solo_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) for (i = 0; i < solo_dev->nr_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }