0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/videodev2.h>
0015 #include <media/v4l2-ioctl.h>
0016
0017 #include "solo6x10.h"
0018
0019 #define SOLO_VCLK_DELAY 3
0020 #define SOLO_PROGRESSIVE_VSIZE 1024
0021
0022 #define SOLO_MOT_THRESH_W 64
0023 #define SOLO_MOT_THRESH_H 64
0024 #define SOLO_MOT_THRESH_SIZE 8192
0025 #define SOLO_MOT_THRESH_REAL (SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
0026 #define SOLO_MOT_FLAG_SIZE 1024
0027 #define SOLO_MOT_FLAG_AREA (SOLO_MOT_FLAG_SIZE * 16)
0028
0029 static void solo_vin_config(struct solo_dev *solo_dev)
0030 {
0031 solo_dev->vin_hstart = 8;
0032 solo_dev->vin_vstart = 2;
0033
0034 solo_reg_write(solo_dev, SOLO_SYS_VCLK,
0035 SOLO_VCLK_SELECT(2) |
0036 SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
0037 SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
0038 SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
0039 SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
0040 SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
0041 SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
0042 SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
0043 SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
0044
0045 solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
0046 SOLO_VI_H_START(solo_dev->vin_hstart) |
0047 SOLO_VI_V_START(solo_dev->vin_vstart) |
0048 SOLO_VI_V_STOP(solo_dev->vin_vstart +
0049 solo_dev->video_vsize));
0050
0051 solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
0052 SOLO_VI_H_START(solo_dev->vout_hstart) |
0053 SOLO_VI_V_START(solo_dev->vout_vstart) |
0054 SOLO_VI_V_STOP(solo_dev->vout_vstart +
0055 solo_dev->video_vsize));
0056
0057 solo_reg_write(solo_dev, SOLO_VI_ACT_P,
0058 SOLO_VI_H_START(0) |
0059 SOLO_VI_V_START(1) |
0060 SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
0061
0062 solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
0063 SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
0064
0065
0066 if (solo_dev->type == SOLO_DEV_6010)
0067 solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
0068 else
0069 solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
0070
0071 solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
0072
0073 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
0074 solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
0075 SOLO_VI_PB_USER_MODE);
0076 solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
0077 SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
0078 solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
0079 SOLO_VI_PB_VSTART(4) |
0080 SOLO_VI_PB_VSTOP(4 + 240));
0081 } else {
0082 solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
0083 SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
0084 solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
0085 SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
0086 solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
0087 SOLO_VI_PB_VSTART(4) |
0088 SOLO_VI_PB_VSTOP(4 + 288));
0089 }
0090 solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
0091 SOLO_VI_PB_HSTOP(16 + 720));
0092 }
0093
0094 static void solo_vout_config_cursor(struct solo_dev *dev)
0095 {
0096 int i;
0097
0098
0099 for (i = 0; i < 20; i++)
0100 solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
0101
0102 solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
0103
0104 solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
0105 (0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
0106 solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
0107 }
0108
0109 static void solo_vout_config(struct solo_dev *solo_dev)
0110 {
0111 solo_dev->vout_hstart = 6;
0112 solo_dev->vout_vstart = 8;
0113
0114 solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
0115 solo_dev->video_type |
0116 SOLO_VO_USER_COLOR_SET_NAV |
0117 SOLO_VO_USER_COLOR_SET_NAH |
0118 SOLO_VO_NA_COLOR_Y(0) |
0119 SOLO_VO_NA_COLOR_CB(0) |
0120 SOLO_VO_NA_COLOR_CR(0));
0121
0122 solo_reg_write(solo_dev, SOLO_VO_ACT_H,
0123 SOLO_VO_H_START(solo_dev->vout_hstart) |
0124 SOLO_VO_H_STOP(solo_dev->vout_hstart +
0125 solo_dev->video_hsize));
0126
0127 solo_reg_write(solo_dev, SOLO_VO_ACT_V,
0128 SOLO_VO_V_START(solo_dev->vout_vstart) |
0129 SOLO_VO_V_STOP(solo_dev->vout_vstart +
0130 solo_dev->video_vsize));
0131
0132 solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
0133 SOLO_VO_H_LEN(solo_dev->video_hsize) |
0134 SOLO_VO_V_LEN(solo_dev->video_vsize));
0135
0136
0137 solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
0138 (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
0139 solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
0140 (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
0141 solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
0142 (16 << 24) | (128 << 16) | (16 << 8) | 128);
0143
0144 solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
0145
0146 solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
0147
0148 solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
0149 solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
0150
0151 solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
0152 SOLO_VO_DISP_ERASE_COUNT(8) |
0153 SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
0154
0155
0156 solo_vout_config_cursor(solo_dev);
0157
0158
0159 solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
0160 (1 << solo_dev->nr_chans) - 1);
0161 }
0162
0163 static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
0164 u16 val, int reg_size)
0165 {
0166 __le16 *buf;
0167 const int n = 64, size = n * sizeof(*buf);
0168 int i, ret = 0;
0169
0170 buf = kmalloc(size, GFP_KERNEL);
0171 if (!buf)
0172 return -ENOMEM;
0173
0174 for (i = 0; i < n; i++)
0175 buf[i] = cpu_to_le16(val);
0176
0177 for (i = 0; i < reg_size; i += size) {
0178 ret = solo_p2m_dma(solo_dev, 1, buf,
0179 SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
0180 size, 0, 0);
0181
0182 if (ret)
0183 break;
0184 }
0185
0186 kfree(buf);
0187 return ret;
0188 }
0189
0190 int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
0191 {
0192 if (ch > solo_dev->nr_chans)
0193 return -EINVAL;
0194
0195 return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
0196 (ch * SOLO_MOT_THRESH_SIZE * 2),
0197 val, SOLO_MOT_THRESH_SIZE);
0198 }
0199
0200 int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
0201 const u16 *thresholds)
0202 {
0203 const unsigned size = sizeof(u16) * 64;
0204 u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
0205 __le16 *buf;
0206 int x, y;
0207 int ret = 0;
0208
0209 buf = kzalloc(size, GFP_KERNEL);
0210 if (buf == NULL)
0211 return -ENOMEM;
0212 for (y = 0; y < SOLO_MOTION_SZ; y++) {
0213 for (x = 0; x < SOLO_MOTION_SZ; x++)
0214 buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
0215 ret |= solo_p2m_dma(solo_dev, 1, buf,
0216 SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * size,
0217 size, 0, 0);
0218 }
0219 kfree(buf);
0220 return ret;
0221 }
0222
0223
0224
0225
0226
0227 static void solo_motion_config(struct solo_dev *solo_dev)
0228 {
0229 int i;
0230
0231 for (i = 0; i < solo_dev->nr_chans; i++) {
0232
0233 solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
0234 SOLO_MOT_FLAG_SIZE);
0235
0236
0237 solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
0238 (i * SOLO_MOT_THRESH_SIZE * 2) +
0239 SOLO_MOT_THRESH_SIZE, 0x0000,
0240 SOLO_MOT_THRESH_SIZE);
0241
0242
0243 solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
0244 }
0245
0246
0247 solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
0248 (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
0249 solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
0250 SOLO_VI_MOTION_FRAME_COUNT(3) |
0251 SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
0252
0253 | SOLO_VI_MOTION_SAMPLE_COUNT(10));
0254
0255 solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
0256 solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
0257 }
0258
0259 int solo_disp_init(struct solo_dev *solo_dev)
0260 {
0261 int i;
0262
0263 solo_dev->video_hsize = 704;
0264 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
0265 solo_dev->video_vsize = 240;
0266 solo_dev->fps = 30;
0267 } else {
0268 solo_dev->video_vsize = 288;
0269 solo_dev->fps = 25;
0270 }
0271
0272 solo_vin_config(solo_dev);
0273 solo_motion_config(solo_dev);
0274 solo_vout_config(solo_dev);
0275
0276 for (i = 0; i < solo_dev->nr_chans; i++)
0277 solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
0278
0279 return 0;
0280 }
0281
0282 void solo_disp_exit(struct solo_dev *solo_dev)
0283 {
0284 int i;
0285
0286 solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
0287 solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
0288 solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
0289
0290 for (i = 0; i < solo_dev->nr_chans; i++) {
0291 solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
0292 solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
0293 solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
0294 }
0295
0296
0297 for (i = 0; i < 5; i++)
0298 solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
0299
0300 for (i = 0; i < 5; i++)
0301 solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
0302
0303 solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
0304 solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
0305
0306 solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
0307 solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
0308 solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
0309
0310 solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
0311 solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
0312 solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
0313 }