~ubuntu-branches/ubuntu/vivid/linux-fsl-imx51/vivid

« back to all changes in this revision

Viewing changes to drivers/mxc/ipu/ipu_ic.c

  • Committer: Bazaar Package Importer
  • Author(s): Andy Whitcroft, Amit Kucheria, Andy Whitcroft, Bryan Wu, Upstream Kernel Changes
  • Date: 2010-01-11 16:26:27 UTC
  • Revision ID: james.westby@ubuntu.com-20100111162627-1q2fl9tcuwcywt1e
Tags: 2.6.31-602.4
[ Amit Kucheria ]

* Update to official 2.6.31 BSP release from Freescale

[ Andy Whitcroft ]

* drop a number of modules no longer built

[ Bryan Wu ]

* [Config] Update configs after applying .31 patchset from Freescale
* [Config] Sync with imx51_defconfig from Freescale BSP

[ Upstream Kernel Changes ]

* Update to official 2.6.31 BSP release from Freescale.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
 
3
 */
 
4
 
 
5
/*
 
6
 * The code contained herein is licensed under the GNU General Public
 
7
 * License. You may obtain a copy of the GNU General Public License
 
8
 * Version 2 or later at the following locations:
 
9
 *
 
10
 * http://www.opensource.org/licenses/gpl-license.html
 
11
 * http://www.gnu.org/copyleft/gpl.html
 
12
 */
 
13
 
 
14
/*
 
15
 * @file ipu_ic.c
 
16
 *
 
17
 * @brief IPU IC functions
 
18
 *
 
19
 * @ingroup IPU
 
20
 */
 
21
#include <linux/types.h>
 
22
#include <linux/init.h>
 
23
#include <linux/errno.h>
 
24
#include <linux/spinlock.h>
 
25
#include <linux/io.h>
 
26
#include <linux/ipu.h>
 
27
 
 
28
#include "ipu_prv.h"
 
29
#include "ipu_regs.h"
 
30
#include "ipu_param_mem.h"
 
31
 
 
32
enum {
 
33
        IC_TASK_VIEWFINDER,
 
34
        IC_TASK_ENCODER,
 
35
        IC_TASK_POST_PROCESSOR
 
36
};
 
37
 
 
38
extern int g_ipu_hw_rev;
 
39
static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
 
40
                      ipu_color_space_t out_format);
 
41
static bool _calc_resize_coeffs(uint32_t inSize, uint32_t outSize,
 
42
                                uint32_t * resizeCoeff,
 
43
                                uint32_t * downsizeCoeff);
 
44
 
 
45
void _ipu_ic_enable_task(ipu_channel_t channel)
 
46
{
 
47
        uint32_t ic_conf;
 
48
 
 
49
        ic_conf = __raw_readl(IC_CONF);
 
50
        switch (channel) {
 
51
        case CSI_PRP_VF_ADC:
 
52
        case MEM_PRP_VF_ADC:
 
53
        case CSI_PRP_VF_MEM:
 
54
        case MEM_PRP_VF_MEM:
 
55
                ic_conf |= IC_CONF_PRPVF_EN;
 
56
                break;
 
57
        case MEM_ROT_VF_MEM:
 
58
                ic_conf |= IC_CONF_PRPVF_ROT_EN;
 
59
                break;
 
60
        case CSI_PRP_ENC_MEM:
 
61
        case MEM_PRP_ENC_MEM:
 
62
                ic_conf |= IC_CONF_PRPENC_EN;
 
63
                break;
 
64
        case MEM_ROT_ENC_MEM:
 
65
                ic_conf |= IC_CONF_PRPENC_ROT_EN;
 
66
                break;
 
67
        case MEM_PP_ADC:
 
68
        case MEM_PP_MEM:
 
69
                ic_conf |= IC_CONF_PP_EN;
 
70
                break;
 
71
        case MEM_ROT_PP_MEM:
 
72
                ic_conf |= IC_CONF_PP_ROT_EN;
 
73
                break;
 
74
        case CSI_MEM:
 
75
                // ???
 
76
                ic_conf |= IC_CONF_RWS_EN | IC_CONF_PRPENC_EN;
 
77
                break;
 
78
        default:
 
79
                break;
 
80
        }
 
81
        __raw_writel(ic_conf, IC_CONF);
 
82
}
 
83
 
 
84
void _ipu_ic_disable_task(ipu_channel_t channel)
 
85
{
 
86
        uint32_t ic_conf;
 
87
 
 
88
        ic_conf = __raw_readl(IC_CONF);
 
89
        switch (channel) {
 
90
        case CSI_PRP_VF_ADC:
 
91
        case MEM_PRP_VF_ADC:
 
92
        case CSI_PRP_VF_MEM:
 
93
        case MEM_PRP_VF_MEM:
 
94
                ic_conf &= ~IC_CONF_PRPVF_EN;
 
95
                break;
 
96
        case MEM_ROT_VF_MEM:
 
97
                ic_conf &= ~IC_CONF_PRPVF_ROT_EN;
 
98
                break;
 
99
        case CSI_PRP_ENC_MEM:
 
100
        case MEM_PRP_ENC_MEM:
 
101
                ic_conf &= ~IC_CONF_PRPENC_EN;
 
102
                break;
 
103
        case MEM_ROT_ENC_MEM:
 
104
                ic_conf &= ~IC_CONF_PRPENC_ROT_EN;
 
105
                break;
 
106
        case MEM_PP_ADC:
 
107
        case MEM_PP_MEM:
 
108
                ic_conf &= ~IC_CONF_PP_EN;
 
109
                break;
 
110
        case MEM_ROT_PP_MEM:
 
111
                ic_conf &= ~IC_CONF_PP_ROT_EN;
 
112
                break;
 
113
        case CSI_MEM:
 
114
                // ???
 
115
                ic_conf &= ~(IC_CONF_RWS_EN | IC_CONF_PRPENC_EN);
 
116
                break;
 
117
        default:
 
118
                break;
 
119
        }
 
120
        __raw_writel(ic_conf, IC_CONF);
 
121
}
 
122
 
 
123
void _ipu_ic_init_prpvf(ipu_channel_params_t * params, bool src_is_csi)
 
124
{
 
125
        uint32_t reg, ic_conf;
 
126
        uint32_t downsizeCoeff, resizeCoeff;
 
127
        ipu_color_space_t in_fmt, out_fmt;
 
128
 
 
129
        /* Setup vertical resizing */
 
130
        _calc_resize_coeffs(params->mem_prp_vf_mem.in_height,
 
131
                            params->mem_prp_vf_mem.out_height,
 
132
                            &resizeCoeff, &downsizeCoeff);
 
133
        reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
 
134
 
 
135
        /* Setup horizontal resizing */
 
136
        _calc_resize_coeffs(params->mem_prp_vf_mem.in_width,
 
137
                            params->mem_prp_vf_mem.out_width,
 
138
                            &resizeCoeff, &downsizeCoeff);
 
139
        reg |= (downsizeCoeff << 14) | resizeCoeff;
 
140
 
 
141
        __raw_writel(reg, IC_PRP_VF_RSC);
 
142
 
 
143
        ic_conf = __raw_readl(IC_CONF);
 
144
 
 
145
        /* Setup color space conversion */
 
146
        in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_pixel_fmt);
 
147
        out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
 
148
        if (in_fmt == RGB) {
 
149
                if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
 
150
                        _init_csc(IC_TASK_VIEWFINDER, RGB, out_fmt);
 
151
                        ic_conf |= IC_CONF_PRPVF_CSC1;  /* Enable RGB->YCBCR CSC */
 
152
                }
 
153
        }
 
154
        if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
 
155
                if (out_fmt == RGB) {
 
156
                        _init_csc(IC_TASK_VIEWFINDER, YCbCr, RGB);
 
157
                        ic_conf |= IC_CONF_PRPVF_CSC1;  /* Enable YCBCR->RGB CSC */
 
158
                } else {
 
159
                        /* TODO: Support YUV<->YCbCr conversion? */
 
160
                }
 
161
        }
 
162
 
 
163
        if (params->mem_prp_vf_mem.graphics_combine_en) {
 
164
                ic_conf |= IC_CONF_PRPVF_CMB;
 
165
 
 
166
                /* need transparent CSC1 conversion */
 
167
                _init_csc(IC_TASK_POST_PROCESSOR, RGB, RGB);
 
168
                ic_conf |= IC_CONF_PRPVF_CSC1;  /* Enable RGB->RGB CSC */
 
169
 
 
170
                if (params->mem_prp_vf_mem.global_alpha_en) {
 
171
                        ic_conf |= IC_CONF_IC_GLB_LOC_A;
 
172
                } else {
 
173
                        ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
 
174
                }
 
175
 
 
176
                if (params->mem_prp_vf_mem.key_color_en) {
 
177
                        ic_conf |= IC_CONF_KEY_COLOR_EN;
 
178
                } else {
 
179
                        ic_conf &= ~IC_CONF_KEY_COLOR_EN;
 
180
                }
 
181
        } else {
 
182
                ic_conf &= ~IC_CONF_PP_CMB;
 
183
        }
 
184
 
 
185
#ifndef CONFIG_VIRTIO_SUPPORT   /* Setting RWS_EN doesn't work in Virtio */
 
186
        if (src_is_csi) {
 
187
                ic_conf &= ~IC_CONF_RWS_EN;
 
188
        } else {
 
189
                ic_conf |= IC_CONF_RWS_EN;
 
190
        }
 
191
#endif
 
192
        __raw_writel(ic_conf, IC_CONF);
 
193
}
 
194
 
 
195
void _ipu_ic_uninit_prpvf(void)
 
196
{
 
197
        uint32_t reg;
 
198
 
 
199
        reg = __raw_readl(IC_CONF);
 
200
        reg &= ~(IC_CONF_PRPVF_EN | IC_CONF_PRPVF_CMB |
 
201
                 IC_CONF_PRPVF_CSC2 | IC_CONF_PRPVF_CSC1);
 
202
        __raw_writel(reg, IC_CONF);
 
203
}
 
204
 
 
205
void _ipu_ic_init_rotate_vf(ipu_channel_params_t * params)
 
206
{
 
207
}
 
208
 
 
209
void _ipu_ic_uninit_rotate_vf(void)
 
210
{
 
211
        uint32_t reg;
 
212
        reg = __raw_readl(IC_CONF);
 
213
        reg &= ~IC_CONF_PRPVF_ROT_EN;
 
214
        __raw_writel(reg, IC_CONF);
 
215
}
 
216
 
 
217
void _ipu_ic_init_csi(ipu_channel_params_t * params)
 
218
{
 
219
        uint32_t reg;
 
220
        reg = __raw_readl(IC_CONF);
 
221
        reg &= ~IC_CONF_CSI_MEM_WR_EN;
 
222
        __raw_writel(reg, IC_CONF);
 
223
}
 
224
 
 
225
void _ipu_ic_uninit_csi(void)
 
226
{
 
227
        uint32_t reg;
 
228
        reg = __raw_readl(IC_CONF);
 
229
        reg &= ~(IC_CONF_RWS_EN | IC_CONF_PRPENC_EN);
 
230
        __raw_writel(reg, IC_CONF);
 
231
}
 
232
 
 
233
void _ipu_ic_init_prpenc(ipu_channel_params_t * params, bool src_is_csi)
 
234
{
 
235
        uint32_t reg, ic_conf;
 
236
        uint32_t downsizeCoeff, resizeCoeff;
 
237
        ipu_color_space_t in_fmt, out_fmt;
 
238
 
 
239
        /* Setup vertical resizing */
 
240
        _calc_resize_coeffs(params->mem_prp_enc_mem.in_height,
 
241
                            params->mem_prp_enc_mem.out_height,
 
242
                            &resizeCoeff, &downsizeCoeff);
 
243
        reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
 
244
 
 
245
        /* Setup horizontal resizing */
 
246
        _calc_resize_coeffs(params->mem_prp_enc_mem.in_width,
 
247
                            params->mem_prp_enc_mem.out_width,
 
248
                            &resizeCoeff, &downsizeCoeff);
 
249
        reg |= (downsizeCoeff << 14) | resizeCoeff;
 
250
 
 
251
        __raw_writel(reg, IC_PRP_ENC_RSC);
 
252
 
 
253
        ic_conf = __raw_readl(IC_CONF);
 
254
 
 
255
        /* Setup color space conversion */
 
256
        in_fmt = format_to_colorspace(params->mem_prp_enc_mem.in_pixel_fmt);
 
257
        out_fmt = format_to_colorspace(params->mem_prp_enc_mem.out_pixel_fmt);
 
258
        if (in_fmt == RGB) {
 
259
                if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
 
260
                        /* TODO: ERROR! */
 
261
                }
 
262
        }
 
263
        if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
 
264
                if (out_fmt == RGB) {
 
265
                        _init_csc(IC_TASK_ENCODER, YCbCr, RGB);
 
266
                        ic_conf |= IC_CONF_PRPENC_CSC1; /* Enable YCBCR->RGB CSC */
 
267
                } else {
 
268
                        /* TODO: Support YUV<->YCbCr conversion? */
 
269
                }
 
270
        }
 
271
 
 
272
        if (src_is_csi) {
 
273
                ic_conf &= ~IC_CONF_RWS_EN;
 
274
        } else {
 
275
                ic_conf |= IC_CONF_RWS_EN;
 
276
        }
 
277
 
 
278
        __raw_writel(ic_conf, IC_CONF);
 
279
}
 
280
 
 
281
void _ipu_ic_uninit_prpenc(void)
 
282
{
 
283
        uint32_t reg;
 
284
 
 
285
        reg = __raw_readl(IC_CONF);
 
286
        reg &= ~(IC_CONF_PRPENC_EN | IC_CONF_PRPENC_CSC1);
 
287
        __raw_writel(reg, IC_CONF);
 
288
}
 
289
 
 
290
void _ipu_ic_init_rotate_enc(ipu_channel_params_t * params)
 
291
{
 
292
}
 
293
 
 
294
void _ipu_ic_uninit_rotate_enc(void)
 
295
{
 
296
        uint32_t reg;
 
297
 
 
298
        reg = __raw_readl(IC_CONF);
 
299
        reg &= ~(IC_CONF_PRPENC_ROT_EN);
 
300
        __raw_writel(reg, IC_CONF);
 
301
}
 
302
 
 
303
void _ipu_ic_init_pp(ipu_channel_params_t * params)
 
304
{
 
305
        uint32_t reg, ic_conf;
 
306
        uint32_t downsizeCoeff, resizeCoeff;
 
307
        ipu_color_space_t in_fmt, out_fmt;
 
308
 
 
309
        /* Setup vertical resizing */
 
310
        _calc_resize_coeffs(params->mem_pp_mem.in_height,
 
311
                            params->mem_pp_mem.out_height,
 
312
                            &resizeCoeff, &downsizeCoeff);
 
313
        reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
 
314
 
 
315
        /* Setup horizontal resizing */
 
316
        _calc_resize_coeffs(params->mem_pp_mem.in_width,
 
317
                            params->mem_pp_mem.out_width,
 
318
                            &resizeCoeff, &downsizeCoeff);
 
319
        reg |= (downsizeCoeff << 14) | resizeCoeff;
 
320
 
 
321
        __raw_writel(reg, IC_PP_RSC);
 
322
 
 
323
        ic_conf = __raw_readl(IC_CONF);
 
324
 
 
325
        /* Setup color space conversion */
 
326
        in_fmt = format_to_colorspace(params->mem_pp_mem.in_pixel_fmt);
 
327
        out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
 
328
        if (in_fmt == RGB) {
 
329
                if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
 
330
                        _init_csc(IC_TASK_POST_PROCESSOR, RGB, out_fmt);
 
331
                        ic_conf |= IC_CONF_PP_CSC2;     /* Enable RGB->YCBCR CSC */
 
332
                }
 
333
        }
 
334
        if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
 
335
                if (out_fmt == RGB) {
 
336
                        _init_csc(IC_TASK_POST_PROCESSOR, YCbCr, RGB);
 
337
                        ic_conf |= IC_CONF_PP_CSC1;     /* Enable YCBCR->RGB CSC */
 
338
                } else {
 
339
                        /* TODO: Support YUV<->YCbCr conversion? */
 
340
                }
 
341
        }
 
342
 
 
343
        if (params->mem_pp_mem.graphics_combine_en) {
 
344
                ic_conf |= IC_CONF_PP_CMB;
 
345
 
 
346
                /* need transparent CSC1 conversion */
 
347
                _init_csc(IC_TASK_POST_PROCESSOR, RGB, RGB);
 
348
                ic_conf |= IC_CONF_PP_CSC1;     /* Enable RGB->RGB CSC */
 
349
 
 
350
                if (params->mem_pp_mem.global_alpha_en) {
 
351
                        ic_conf |= IC_CONF_IC_GLB_LOC_A;
 
352
                } else {
 
353
                        ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
 
354
                }
 
355
 
 
356
                if (params->mem_pp_mem.key_color_en) {
 
357
                        ic_conf |= IC_CONF_KEY_COLOR_EN;
 
358
                } else {
 
359
                        ic_conf &= ~IC_CONF_KEY_COLOR_EN;
 
360
                }
 
361
        } else {
 
362
                ic_conf &= ~IC_CONF_PP_CMB;
 
363
        }
 
364
 
 
365
        __raw_writel(ic_conf, IC_CONF);
 
366
}
 
367
 
 
368
void _ipu_ic_uninit_pp(void)
 
369
{
 
370
        uint32_t reg;
 
371
 
 
372
        reg = __raw_readl(IC_CONF);
 
373
        reg &= ~(IC_CONF_PP_EN | IC_CONF_PP_CSC1 | IC_CONF_PP_CSC2 |
 
374
                 IC_CONF_PP_CMB);
 
375
        __raw_writel(reg, IC_CONF);
 
376
}
 
377
 
 
378
void _ipu_ic_init_rotate_pp(ipu_channel_params_t * params)
 
379
{
 
380
}
 
381
 
 
382
void _ipu_ic_uninit_rotate_pp(void)
 
383
{
 
384
        uint32_t reg;
 
385
        reg = __raw_readl(IC_CONF);
 
386
        reg &= ~IC_CONF_PP_ROT_EN;
 
387
        __raw_writel(reg, IC_CONF);
 
388
}
 
389
 
 
390
static void _init_csc(uint8_t ic_task, ipu_color_space_t in_format,
 
391
                      ipu_color_space_t out_format)
 
392
{
 
393
/*     Y = R *  .299 + G *  .587 + B *  .114;
 
394
       U = R * -.169 + G * -.332 + B *  .500 + 128.;
 
395
       V = R *  .500 + G * -.419 + B * -.0813 + 128.;*/
 
396
        static const uint32_t rgb2ycbcr_coeff[4][3] = {
 
397
                {0x004D, 0x0096, 0x001D},
 
398
                {0x01D5, 0x01AB, 0x0080},
 
399
                {0x0080, 0x0195, 0x01EB},
 
400
                {0x0000, 0x0200, 0x0200},       /* A0, A1, A2 */
 
401
        };
 
402
 
 
403
        /* transparent RGB->RGB matrix for combining
 
404
         */
 
405
        static const uint32_t rgb2rgb_coeff[4][3] = {
 
406
                {0x0080, 0x0000, 0x0000},
 
407
                {0x0000, 0x0080, 0x0000},
 
408
                {0x0000, 0x0000, 0x0080},
 
409
                {0x0000, 0x0000, 0x0000},       /* A0, A1, A2 */
 
410
        };
 
411
 
 
412
/*     R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
 
413
       G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
 
414
       B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
 
415
        static const uint32_t ycbcr2rgb_coeff[4][3] = {
 
416
                {149, 0, 204},
 
417
                {149, 462, 408},
 
418
                {149, 255, 0},
 
419
                {8192 - 446, 266, 8192 - 554},  /* A0, A1, A2 */
 
420
        };
 
421
 
 
422
        uint32_t param[2];
 
423
        uint32_t address = 0;
 
424
 
 
425
        if (g_ipu_hw_rev > 1) {
 
426
                if (ic_task == IC_TASK_VIEWFINDER) {
 
427
                        address = 0x645 << 3;
 
428
                } else if (ic_task == IC_TASK_ENCODER) {
 
429
                        address = 0x321 << 3;
 
430
                } else if (ic_task == IC_TASK_POST_PROCESSOR) {
 
431
                        address = 0x96C << 3;
 
432
                } else {
 
433
                        BUG();
 
434
                }
 
435
        } else {
 
436
                if (ic_task == IC_TASK_VIEWFINDER) {
 
437
                        address = 0x5a5 << 3;
 
438
                } else if (ic_task == IC_TASK_ENCODER) {
 
439
                        address = 0x2d1 << 3;
 
440
                } else if (ic_task == IC_TASK_POST_PROCESSOR) {
 
441
                        address = 0x87c << 3;
 
442
                } else {
 
443
                        BUG();
 
444
                }
 
445
        }
 
446
 
 
447
        if ((in_format == YCbCr) && (out_format == RGB)) {
 
448
                /* Init CSC1 (YCbCr->RGB) */
 
449
                param[0] =
 
450
                    (ycbcr2rgb_coeff[3][0] << 27) | (ycbcr2rgb_coeff[0][0] <<
 
451
                                                     18) |
 
452
                    (ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
 
453
                /* scale = 2, sat = 0 */
 
454
                param[1] = (ycbcr2rgb_coeff[3][0] >> 5) | (2L << (40 - 32));
 
455
                _ipu_write_param_mem(address, param, 2);
 
456
                dev_dbg(g_ipu_dev,
 
457
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
458
                        address, param[0], param[1]);
 
459
 
 
460
                param[0] =
 
461
                    (ycbcr2rgb_coeff[3][1] << 27) | (ycbcr2rgb_coeff[0][1] <<
 
462
                                                     18) |
 
463
                    (ycbcr2rgb_coeff[1][0] << 9) | ycbcr2rgb_coeff[2][0];
 
464
                param[1] = (ycbcr2rgb_coeff[3][1] >> 5);
 
465
                address += 1L << 3;
 
466
                _ipu_write_param_mem(address, param, 2);
 
467
                dev_dbg(g_ipu_dev,
 
468
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
469
                        address, param[0], param[1]);
 
470
 
 
471
                param[0] =
 
472
                    (ycbcr2rgb_coeff[3][2] << 27) | (ycbcr2rgb_coeff[0][2] <<
 
473
                                                     18) |
 
474
                    (ycbcr2rgb_coeff[1][2] << 9) | ycbcr2rgb_coeff[2][1];
 
475
                param[1] = (ycbcr2rgb_coeff[3][2] >> 5);
 
476
                address += 1L << 3;
 
477
                _ipu_write_param_mem(address, param, 2);
 
478
                dev_dbg(g_ipu_dev,
 
479
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
480
                        address, param[0], param[1]);
 
481
        } else if ((in_format == RGB) && (out_format == YCbCr)) {
 
482
                /* Init CSC1 (RGB->YCbCr) */
 
483
                param[0] =
 
484
                    (rgb2ycbcr_coeff[3][0] << 27) | (rgb2ycbcr_coeff[0][0] <<
 
485
                                                     18) |
 
486
                    (rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
 
487
                /* scale = 1, sat = 0 */
 
488
                param[1] = (rgb2ycbcr_coeff[3][0] >> 5) | (1UL << 8);
 
489
                _ipu_write_param_mem(address, param, 2);
 
490
                dev_dbg(g_ipu_dev,
 
491
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
492
                        address, param[0], param[1]);
 
493
 
 
494
                param[0] =
 
495
                    (rgb2ycbcr_coeff[3][1] << 27) | (rgb2ycbcr_coeff[0][1] <<
 
496
                                                     18) |
 
497
                    (rgb2ycbcr_coeff[1][0] << 9) | rgb2ycbcr_coeff[2][0];
 
498
                param[1] = (rgb2ycbcr_coeff[3][1] >> 5);
 
499
                address += 1L << 3;
 
500
                _ipu_write_param_mem(address, param, 2);
 
501
                dev_dbg(g_ipu_dev,
 
502
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
503
                        address, param[0], param[1]);
 
504
 
 
505
                param[0] =
 
506
                    (rgb2ycbcr_coeff[3][2] << 27) | (rgb2ycbcr_coeff[0][2] <<
 
507
                                                     18) |
 
508
                    (rgb2ycbcr_coeff[1][2] << 9) | rgb2ycbcr_coeff[2][1];
 
509
                param[1] = (rgb2ycbcr_coeff[3][2] >> 5);
 
510
                address += 1L << 3;
 
511
                _ipu_write_param_mem(address, param, 2);
 
512
                dev_dbg(g_ipu_dev,
 
513
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
514
                        address, param[0], param[1]);
 
515
        } else if ((in_format == RGB) && (out_format == RGB)) {
 
516
                /* Init CSC1 */
 
517
                param[0] =
 
518
                    (rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
 
519
                    (rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
 
520
                /* scale = 2, sat = 0 */
 
521
                param[1] = (rgb2rgb_coeff[3][0] >> 5) | (2UL << 8);
 
522
 
 
523
                _ipu_write_param_mem(address, param, 2);
 
524
 
 
525
                dev_dbg(g_ipu_dev,
 
526
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
527
                        address, param[0], param[1]);
 
528
 
 
529
                param[0] =
 
530
                    (rgb2rgb_coeff[3][1] << 27) | (rgb2rgb_coeff[0][1] << 18) |
 
531
                    (rgb2rgb_coeff[1][0] << 9) | rgb2rgb_coeff[2][0];
 
532
                param[1] = (rgb2rgb_coeff[3][1] >> 5);
 
533
 
 
534
                address += 1L << 3;
 
535
                _ipu_write_param_mem(address, param, 2);
 
536
 
 
537
                dev_dbg(g_ipu_dev,
 
538
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
539
                        address, param[0], param[1]);
 
540
 
 
541
                param[0] =
 
542
                    (rgb2rgb_coeff[3][2] << 27) | (rgb2rgb_coeff[0][2] << 18) |
 
543
                    (rgb2rgb_coeff[1][2] << 9) | rgb2rgb_coeff[2][1];
 
544
                param[1] = (rgb2rgb_coeff[3][2] >> 5);
 
545
 
 
546
                address += 1L << 3;
 
547
                _ipu_write_param_mem(address, param, 2);
 
548
 
 
549
                dev_dbg(g_ipu_dev,
 
550
                        "addr 0x%04X: word0 = 0x%08X, word1 = 0x%08X\n",
 
551
                        address, param[0], param[1]);
 
552
        } else {
 
553
                dev_err(g_ipu_dev, "Unsupported color space conversion\n");
 
554
        }
 
555
}
 
556
 
 
557
static bool _calc_resize_coeffs(uint32_t inSize, uint32_t outSize,
 
558
                                uint32_t * resizeCoeff,
 
559
                                uint32_t * downsizeCoeff)
 
560
{
 
561
        uint32_t tempSize;
 
562
        uint32_t tempDownsize;
 
563
 
 
564
        /* Cannot downsize more than 8:1 */
 
565
        if ((outSize << 3) < inSize) {
 
566
                return false;
 
567
        }
 
568
        /* compute downsizing coefficient */
 
569
        tempDownsize = 0;
 
570
        tempSize = inSize;
 
571
        while ((tempSize >= outSize * 2) && (tempDownsize < 2)) {
 
572
                tempSize >>= 1;
 
573
                tempDownsize++;
 
574
        }
 
575
        *downsizeCoeff = tempDownsize;
 
576
 
 
577
        /* compute resizing coefficient using the following equation:
 
578
           resizeCoeff = M*(SI -1)/(SO - 1)
 
579
           where M = 2^13, SI - input size, SO - output size    */
 
580
        *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
 
581
        if (*resizeCoeff >= 16384L) {
 
582
                dev_err(g_ipu_dev, "Warning! Overflow on resize coeff.\n");
 
583
                *resizeCoeff = 0x3FFF;
 
584
        }
 
585
 
 
586
        dev_dbg(g_ipu_dev, "resizing from %u -> %u pixels, "
 
587
                "downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
 
588
                *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
 
589
                ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
 
590
 
 
591
        return true;
 
592
}