1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "mixer.h"
15#include "regs-mixer.h"
16#include "regs-vp.h"
17
18#include <linux/delay.h>
19
20
21
22static inline u32 vp_read(struct mxr_device *mdev, u32 reg_id)
23{
24 return readl(mdev->res.vp_regs + reg_id);
25}
26
27static inline void vp_write(struct mxr_device *mdev, u32 reg_id, u32 val)
28{
29 writel(val, mdev->res.vp_regs + reg_id);
30}
31
32static inline void vp_write_mask(struct mxr_device *mdev, u32 reg_id,
33 u32 val, u32 mask)
34{
35 u32 old = vp_read(mdev, reg_id);
36
37 val = (val & mask) | (old & ~mask);
38 writel(val, mdev->res.vp_regs + reg_id);
39}
40
41static inline u32 mxr_read(struct mxr_device *mdev, u32 reg_id)
42{
43 return readl(mdev->res.mxr_regs + reg_id);
44}
45
46static inline void mxr_write(struct mxr_device *mdev, u32 reg_id, u32 val)
47{
48 writel(val, mdev->res.mxr_regs + reg_id);
49}
50
51static inline void mxr_write_mask(struct mxr_device *mdev, u32 reg_id,
52 u32 val, u32 mask)
53{
54 u32 old = mxr_read(mdev, reg_id);
55
56 val = (val & mask) | (old & ~mask);
57 writel(val, mdev->res.mxr_regs + reg_id);
58}
59
60void mxr_vsync_set_update(struct mxr_device *mdev, int en)
61{
62
63 mxr_write_mask(mdev, MXR_STATUS, en ? MXR_STATUS_SYNC_ENABLE : 0,
64 MXR_STATUS_SYNC_ENABLE);
65 vp_write(mdev, VP_SHADOW_UPDATE, en ? VP_SHADOW_UPDATE_ENABLE : 0);
66}
67
68static void __mxr_reg_vp_reset(struct mxr_device *mdev)
69{
70 int tries = 100;
71
72 vp_write(mdev, VP_SRESET, VP_SRESET_PROCESSING);
73 for (tries = 100; tries; --tries) {
74
75 if (~vp_read(mdev, VP_SRESET) & VP_SRESET_PROCESSING)
76 break;
77 mdelay(10);
78 }
79 WARN(tries == 0, "failed to reset Video Processor\n");
80}
81
82static void mxr_reg_vp_default_filter(struct mxr_device *mdev);
83
84void mxr_reg_reset(struct mxr_device *mdev)
85{
86 unsigned long flags;
87 u32 val;
88
89 spin_lock_irqsave(&mdev->reg_slock, flags);
90 mxr_vsync_set_update(mdev, MXR_DISABLE);
91
92
93 mxr_write(mdev, MXR_CFG, MXR_CFG_OUT_RGB888);
94
95
96 mxr_write_mask(mdev, MXR_STATUS, MXR_STATUS_16_BURST,
97 MXR_STATUS_BURST_MASK);
98
99
100
101
102
103
104
105 val = MXR_LAYER_CFG_GRP0_VAL(1);
106 val |= MXR_LAYER_CFG_VP_VAL(2);
107 val |= MXR_LAYER_CFG_GRP1_VAL(3);
108 mxr_write(mdev, MXR_LAYER_CFG, val);
109
110
111 mxr_write(mdev, MXR_BG_COLOR0, 0x808080);
112 mxr_write(mdev, MXR_BG_COLOR1, 0x808080);
113 mxr_write(mdev, MXR_BG_COLOR2, 0x808080);
114
115
116
117 val = MXR_GRP_CFG_COLOR_KEY_DISABLE;
118 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
119 val |= MXR_GRP_CFG_ALPHA_VAL(0xff);
120
121
122 mxr_write(mdev, MXR_GRAPHIC_CFG(0), val);
123 mxr_write(mdev, MXR_GRAPHIC_CFG(1), val);
124
125
126 __mxr_reg_vp_reset(mdev);
127 mxr_reg_vp_default_filter(mdev);
128
129
130 mxr_write_mask(mdev, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
131
132 mxr_vsync_set_update(mdev, MXR_ENABLE);
133 spin_unlock_irqrestore(&mdev->reg_slock, flags);
134}
135
136void mxr_reg_graph_format(struct mxr_device *mdev, int idx,
137 const struct mxr_format *fmt, const struct mxr_geometry *geo)
138{
139 u32 val;
140 unsigned long flags;
141
142 spin_lock_irqsave(&mdev->reg_slock, flags);
143 mxr_vsync_set_update(mdev, MXR_DISABLE);
144
145
146 mxr_write_mask(mdev, MXR_GRAPHIC_CFG(idx),
147 MXR_GRP_CFG_FORMAT_VAL(fmt->cookie), MXR_GRP_CFG_FORMAT_MASK);
148
149
150 mxr_write(mdev, MXR_GRAPHIC_SPAN(idx), geo->src.full_width);
151 val = MXR_GRP_WH_WIDTH(geo->src.width);
152 val |= MXR_GRP_WH_HEIGHT(geo->src.height);
153 val |= MXR_GRP_WH_H_SCALE(geo->x_ratio);
154 val |= MXR_GRP_WH_V_SCALE(geo->y_ratio);
155 mxr_write(mdev, MXR_GRAPHIC_WH(idx), val);
156
157
158 val = MXR_GRP_SXY_SX(geo->src.x_offset);
159 val |= MXR_GRP_SXY_SY(geo->src.y_offset);
160 mxr_write(mdev, MXR_GRAPHIC_SXY(idx), val);
161
162
163 val = MXR_GRP_DXY_DX(geo->dst.x_offset);
164 val |= MXR_GRP_DXY_DY(geo->dst.y_offset);
165 mxr_write(mdev, MXR_GRAPHIC_DXY(idx), val);
166
167 mxr_vsync_set_update(mdev, MXR_ENABLE);
168 spin_unlock_irqrestore(&mdev->reg_slock, flags);
169}
170
171void mxr_reg_vp_format(struct mxr_device *mdev,
172 const struct mxr_format *fmt, const struct mxr_geometry *geo)
173{
174 unsigned long flags;
175
176 spin_lock_irqsave(&mdev->reg_slock, flags);
177 mxr_vsync_set_update(mdev, MXR_DISABLE);
178
179 vp_write_mask(mdev, VP_MODE, fmt->cookie, VP_MODE_FMT_MASK);
180
181
182 vp_write(mdev, VP_IMG_SIZE_Y, VP_IMG_HSIZE(geo->src.full_width) |
183 VP_IMG_VSIZE(geo->src.full_height));
184
185 vp_write(mdev, VP_IMG_SIZE_C, VP_IMG_HSIZE(geo->src.full_width) |
186 VP_IMG_VSIZE(geo->src.full_height / 2));
187
188 vp_write(mdev, VP_SRC_WIDTH, geo->src.width);
189 vp_write(mdev, VP_SRC_HEIGHT, geo->src.height);
190 vp_write(mdev, VP_SRC_H_POSITION,
191 VP_SRC_H_POSITION_VAL(geo->src.x_offset));
192 vp_write(mdev, VP_SRC_V_POSITION, geo->src.y_offset);
193
194 vp_write(mdev, VP_DST_WIDTH, geo->dst.width);
195 vp_write(mdev, VP_DST_H_POSITION, geo->dst.x_offset);
196 if (geo->dst.field == V4L2_FIELD_INTERLACED) {
197 vp_write(mdev, VP_DST_HEIGHT, geo->dst.height / 2);
198 vp_write(mdev, VP_DST_V_POSITION, geo->dst.y_offset / 2);
199 } else {
200 vp_write(mdev, VP_DST_HEIGHT, geo->dst.height);
201 vp_write(mdev, VP_DST_V_POSITION, geo->dst.y_offset);
202 }
203
204 vp_write(mdev, VP_H_RATIO, geo->x_ratio);
205 vp_write(mdev, VP_V_RATIO, geo->y_ratio);
206
207 vp_write(mdev, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
208
209 mxr_vsync_set_update(mdev, MXR_ENABLE);
210 spin_unlock_irqrestore(&mdev->reg_slock, flags);
211
212}
213
214void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr)
215{
216 u32 val = addr ? ~0 : 0;
217 unsigned long flags;
218
219 spin_lock_irqsave(&mdev->reg_slock, flags);
220 mxr_vsync_set_update(mdev, MXR_DISABLE);
221
222 if (idx == 0)
223 mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
224 else
225 mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
226 mxr_write(mdev, MXR_GRAPHIC_BASE(idx), addr);
227
228 mxr_vsync_set_update(mdev, MXR_ENABLE);
229 spin_unlock_irqrestore(&mdev->reg_slock, flags);
230}
231
232void mxr_reg_vp_buffer(struct mxr_device *mdev,
233 dma_addr_t luma_addr[2], dma_addr_t chroma_addr[2])
234{
235 u32 val = luma_addr[0] ? ~0 : 0;
236 unsigned long flags;
237
238 spin_lock_irqsave(&mdev->reg_slock, flags);
239 mxr_vsync_set_update(mdev, MXR_DISABLE);
240
241 mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_VP_ENABLE);
242 vp_write_mask(mdev, VP_ENABLE, val, VP_ENABLE_ON);
243
244 vp_write(mdev, VP_TOP_Y_PTR, luma_addr[0]);
245 vp_write(mdev, VP_TOP_C_PTR, chroma_addr[0]);
246 vp_write(mdev, VP_BOT_Y_PTR, luma_addr[1]);
247 vp_write(mdev, VP_BOT_C_PTR, chroma_addr[1]);
248
249 mxr_vsync_set_update(mdev, MXR_ENABLE);
250 spin_unlock_irqrestore(&mdev->reg_slock, flags);
251}
252
253static void mxr_irq_layer_handle(struct mxr_layer *layer)
254{
255 struct list_head *head = &layer->enq_list;
256 struct mxr_buffer *done;
257
258
259 if (layer == NULL)
260 return;
261
262 spin_lock(&layer->enq_slock);
263 if (layer->state == MXR_LAYER_IDLE)
264 goto done;
265
266 done = layer->shadow_buf;
267 layer->shadow_buf = layer->update_buf;
268
269 if (list_empty(head)) {
270 if (layer->state != MXR_LAYER_STREAMING)
271 layer->update_buf = NULL;
272 } else {
273 struct mxr_buffer *next;
274 next = list_first_entry(head, struct mxr_buffer, list);
275 list_del(&next->list);
276 layer->update_buf = next;
277 }
278
279 layer->ops.buffer_set(layer, layer->update_buf);
280
281 if (done && done != layer->shadow_buf)
282 vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE);
283
284done:
285 spin_unlock(&layer->enq_slock);
286}
287
288irqreturn_t mxr_irq_handler(int irq, void *dev_data)
289{
290 struct mxr_device *mdev = dev_data;
291 u32 i, val;
292
293 spin_lock(&mdev->reg_slock);
294 val = mxr_read(mdev, MXR_INT_STATUS);
295
296
297 if (val & MXR_INT_STATUS_VSYNC) {
298 set_bit(MXR_EVENT_VSYNC, &mdev->event_flags);
299 wake_up(&mdev->event_queue);
300 }
301
302
303 if (~val & MXR_INT_EN_VSYNC) {
304
305 val &= ~MXR_INT_EN_VSYNC;
306 val |= MXR_INT_CLEAR_VSYNC;
307 }
308 mxr_write(mdev, MXR_INT_STATUS, val);
309
310 spin_unlock(&mdev->reg_slock);
311
312 if (~val & MXR_INT_CLEAR_VSYNC)
313 return IRQ_HANDLED;
314 for (i = 0; i < MXR_MAX_LAYERS; ++i)
315 mxr_irq_layer_handle(mdev->layer[i]);
316 return IRQ_HANDLED;
317}
318
319void mxr_reg_s_output(struct mxr_device *mdev, int cookie)
320{
321 u32 val;
322
323 val = cookie == 0 ? MXR_CFG_DST_SDO : MXR_CFG_DST_HDMI;
324 mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_DST_MASK);
325}
326
327void mxr_reg_streamon(struct mxr_device *mdev)
328{
329 unsigned long flags;
330
331 spin_lock_irqsave(&mdev->reg_slock, flags);
332
333
334
335 mxr_write_mask(mdev, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
336
337 spin_unlock_irqrestore(&mdev->reg_slock, flags);
338}
339
340void mxr_reg_streamoff(struct mxr_device *mdev)
341{
342 unsigned long flags;
343
344 spin_lock_irqsave(&mdev->reg_slock, flags);
345
346
347
348 mxr_write_mask(mdev, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
349
350 spin_unlock_irqrestore(&mdev->reg_slock, flags);
351}
352
353int mxr_reg_wait4vsync(struct mxr_device *mdev)
354{
355 int ret;
356
357 clear_bit(MXR_EVENT_VSYNC, &mdev->event_flags);
358
359 ret = wait_event_timeout(mdev->event_queue,
360 test_bit(MXR_EVENT_VSYNC, &mdev->event_flags),
361 msecs_to_jiffies(1000));
362 if (ret > 0)
363 return 0;
364 if (ret < 0)
365 return ret;
366 mxr_warn(mdev, "no vsync detected - timeout\n");
367 return -ETIME;
368}
369
370void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
371 struct v4l2_mbus_framefmt *fmt)
372{
373 u32 val = 0;
374 unsigned long flags;
375
376 spin_lock_irqsave(&mdev->reg_slock, flags);
377 mxr_vsync_set_update(mdev, MXR_DISABLE);
378
379
380 if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
381 val |= MXR_CFG_OUT_YUV444;
382 else
383 val |= MXR_CFG_OUT_RGB888;
384
385
386 if (fmt->field == V4L2_FIELD_INTERLACED)
387 val |= MXR_CFG_SCAN_INTERLACE;
388 else
389 val |= MXR_CFG_SCAN_PROGRASSIVE;
390
391
392 if (fmt->height == 480)
393 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
394 else if (fmt->height == 576)
395 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
396 else if (fmt->height == 720)
397 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
398 else if (fmt->height == 1080)
399 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
400 else
401 WARN(1, "unrecognized mbus height %u!\n", fmt->height);
402
403 mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK |
404 MXR_CFG_OUT_MASK);
405
406 val = (fmt->field == V4L2_FIELD_INTERLACED) ? ~0 : 0;
407 vp_write_mask(mdev, VP_MODE, val,
408 VP_MODE_LINE_SKIP | VP_MODE_FIELD_ID_AUTO_TOGGLING);
409
410 mxr_vsync_set_update(mdev, MXR_ENABLE);
411 spin_unlock_irqrestore(&mdev->reg_slock, flags);
412}
413
414void mxr_reg_graph_layer_stream(struct mxr_device *mdev, int idx, int en)
415{
416
417}
418
419void mxr_reg_vp_layer_stream(struct mxr_device *mdev, int en)
420{
421
422}
423
424static const u8 filter_y_horiz_tap8[] = {
425 0, -1, -1, -1, -1, -1, -1, -1,
426 -1, -1, -1, -1, -1, 0, 0, 0,
427 0, 2, 4, 5, 6, 6, 6, 6,
428 6, 5, 5, 4, 3, 2, 1, 1,
429 0, -6, -12, -16, -18, -20, -21, -20,
430 -20, -18, -16, -13, -10, -8, -5, -2,
431 127, 126, 125, 121, 114, 107, 99, 89,
432 79, 68, 57, 46, 35, 25, 16, 8,
433};
434
435static const u8 filter_y_vert_tap4[] = {
436 0, -3, -6, -8, -8, -8, -8, -7,
437 -6, -5, -4, -3, -2, -1, -1, 0,
438 127, 126, 124, 118, 111, 102, 92, 81,
439 70, 59, 48, 37, 27, 19, 11, 5,
440 0, 5, 11, 19, 27, 37, 48, 59,
441 70, 81, 92, 102, 111, 118, 124, 126,
442 0, 0, -1, -1, -2, -3, -4, -5,
443 -6, -7, -8, -8, -8, -8, -6, -3,
444};
445
446static const u8 filter_cr_horiz_tap4[] = {
447 0, -3, -6, -8, -8, -8, -8, -7,
448 -6, -5, -4, -3, -2, -1, -1, 0,
449 127, 126, 124, 118, 111, 102, 92, 81,
450 70, 59, 48, 37, 27, 19, 11, 5,
451};
452
453static inline void mxr_reg_vp_filter_set(struct mxr_device *mdev,
454 int reg_id, const u8 *data, unsigned int size)
455{
456
457 BUG_ON(size & 3);
458 for (; size; size -= 4, reg_id += 4, data += 4) {
459 u32 val = (data[0] << 24) | (data[1] << 16) |
460 (data[2] << 8) | data[3];
461 vp_write(mdev, reg_id, val);
462 }
463}
464
465static void mxr_reg_vp_default_filter(struct mxr_device *mdev)
466{
467 mxr_reg_vp_filter_set(mdev, VP_POLY8_Y0_LL,
468 filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
469 mxr_reg_vp_filter_set(mdev, VP_POLY4_Y0_LL,
470 filter_y_vert_tap4, sizeof filter_y_vert_tap4);
471 mxr_reg_vp_filter_set(mdev, VP_POLY4_C0_LL,
472 filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
473}
474
475static void mxr_reg_mxr_dump(struct mxr_device *mdev)
476{
477#define DUMPREG(reg_id) \
478do { \
479 mxr_dbg(mdev, #reg_id " = %08x\n", \
480 (u32)readl(mdev->res.mxr_regs + reg_id)); \
481} while (0)
482
483 DUMPREG(MXR_STATUS);
484 DUMPREG(MXR_CFG);
485 DUMPREG(MXR_INT_EN);
486 DUMPREG(MXR_INT_STATUS);
487
488 DUMPREG(MXR_LAYER_CFG);
489 DUMPREG(MXR_VIDEO_CFG);
490
491 DUMPREG(MXR_GRAPHIC0_CFG);
492 DUMPREG(MXR_GRAPHIC0_BASE);
493 DUMPREG(MXR_GRAPHIC0_SPAN);
494 DUMPREG(MXR_GRAPHIC0_WH);
495 DUMPREG(MXR_GRAPHIC0_SXY);
496 DUMPREG(MXR_GRAPHIC0_DXY);
497
498 DUMPREG(MXR_GRAPHIC1_CFG);
499 DUMPREG(MXR_GRAPHIC1_BASE);
500 DUMPREG(MXR_GRAPHIC1_SPAN);
501 DUMPREG(MXR_GRAPHIC1_WH);
502 DUMPREG(MXR_GRAPHIC1_SXY);
503 DUMPREG(MXR_GRAPHIC1_DXY);
504#undef DUMPREG
505}
506
507static void mxr_reg_vp_dump(struct mxr_device *mdev)
508{
509#define DUMPREG(reg_id) \
510do { \
511 mxr_dbg(mdev, #reg_id " = %08x\n", \
512 (u32) readl(mdev->res.vp_regs + reg_id)); \
513} while (0)
514
515
516 DUMPREG(VP_ENABLE);
517 DUMPREG(VP_SRESET);
518 DUMPREG(VP_SHADOW_UPDATE);
519 DUMPREG(VP_FIELD_ID);
520 DUMPREG(VP_MODE);
521 DUMPREG(VP_IMG_SIZE_Y);
522 DUMPREG(VP_IMG_SIZE_C);
523 DUMPREG(VP_PER_RATE_CTRL);
524 DUMPREG(VP_TOP_Y_PTR);
525 DUMPREG(VP_BOT_Y_PTR);
526 DUMPREG(VP_TOP_C_PTR);
527 DUMPREG(VP_BOT_C_PTR);
528 DUMPREG(VP_ENDIAN_MODE);
529 DUMPREG(VP_SRC_H_POSITION);
530 DUMPREG(VP_SRC_V_POSITION);
531 DUMPREG(VP_SRC_WIDTH);
532 DUMPREG(VP_SRC_HEIGHT);
533 DUMPREG(VP_DST_H_POSITION);
534 DUMPREG(VP_DST_V_POSITION);
535 DUMPREG(VP_DST_WIDTH);
536 DUMPREG(VP_DST_HEIGHT);
537 DUMPREG(VP_H_RATIO);
538 DUMPREG(VP_V_RATIO);
539
540#undef DUMPREG
541}
542
543void mxr_reg_dump(struct mxr_device *mdev)
544{
545 mxr_reg_mxr_dump(mdev);
546 mxr_reg_vp_dump(mdev);
547}
548
549