fix rga prescale mode dst height bug
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rga / RGA_API.c
1 \r
2 #include <linux/memory.h>\r
3 #include "RGA_API.h"\r
4 #include "rga.h"\r
5 //#include "rga_angle.h"\r
6 \r
7 #define IS_YUV_420(format) \\r
8      ((format == RK_FORMAT_YCbCr_420_P) | (format == RK_FORMAT_YCbCr_420_SP) | \\r
9       (format == RK_FORMAT_YCrCb_420_P) | (format == RK_FORMAT_YCrCb_420_SP))  \r
10 \r
11 #define IS_YUV_422(format) \\r
12      ((format == RK_FORMAT_YCbCr_422_P) | (format == RK_FORMAT_YCbCr_422_SP) | \\r
13       (format == RK_FORMAT_YCrCb_422_P) | (format == RK_FORMAT_YCrCb_422_SP))   \r
14 \r
15 #define IS_YUV(format) \\r
16      ((format == RK_FORMAT_YCbCr_420_P) | (format == RK_FORMAT_YCbCr_420_SP) | \\r
17       (format == RK_FORMAT_YCrCb_420_P) | (format == RK_FORMAT_YCrCb_420_SP) | \\r
18       (format == RK_FORMAT_YCbCr_422_P) | (format == RK_FORMAT_YCbCr_422_SP) | \\r
19       (format == RK_FORMAT_YCrCb_422_P) | (format == RK_FORMAT_YCrCb_422_SP))\r
20             \r
21 \r
22 extern rga_service_info rga_service;\r
23 \r
24 \r
25 void\r
26 matrix_cal(const struct rga_req *msg, TILE_INFO *tile)\r
27 {\r
28     uint32_t x_time, y_time;\r
29     uint64_t sina, cosa;\r
30 \r
31     int s_act_w, s_act_h, d_act_w, d_act_h;\r
32 \r
33     s_act_w = msg->src.act_w;\r
34     s_act_h = msg->src.act_h;\r
35     d_act_w = msg->dst.act_w;\r
36     d_act_h = msg->dst.act_h;\r
37 \r
38     if (s_act_w == 1) s_act_w += 1;\r
39     if (s_act_h == 1) s_act_h += 1;\r
40     if (d_act_h == 1) d_act_h += 1;\r
41     if (d_act_w == 1) d_act_w += 1;\r
42 \r
43     x_time = ((s_act_w - 1)<<16) / (d_act_w - 1);\r
44     y_time = ((s_act_h - 1)<<16) / (d_act_h - 1);\r
45     \r
46     sina = msg->sina;\r
47     cosa = msg->cosa;\r
48 \r
49     switch(msg->rotate_mode)\r
50     {\r
51         /* 16.16 x 16.16 */\r
52         /* matrix[] is 64 bit wide */\r
53         case 1 :\r
54             tile->matrix[0] =  cosa*x_time;    \r
55             tile->matrix[1] = -sina*y_time;      \r
56             tile->matrix[2] =  sina*x_time;       \r
57             tile->matrix[3] =  cosa*y_time;\r
58             break;\r
59         case 2 :\r
60             tile->matrix[0] = -(x_time<<16);       \r
61             tile->matrix[1] = 0;      \r
62             tile->matrix[2] = 0;       \r
63             tile->matrix[3] = (y_time<<16);\r
64             break;\r
65         case 3 :\r
66             tile->matrix[0] = (x_time<<16);       \r
67             tile->matrix[1] = 0;      \r
68             tile->matrix[2] = 0;       \r
69             tile->matrix[3] = -(y_time<<16);\r
70             break;\r
71         default :\r
72             tile->matrix[0] =  (uint64_t)1<<32;       \r
73             tile->matrix[1] =  0;      \r
74             tile->matrix[2] =  0;       \r
75             tile->matrix[3] =  (uint64_t)1<<32;\r
76             break;            \r
77     }    \r
78 }\r
79 \r
80 \r
81 int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1)\r
82 {\r
83     \r
84     struct rga_req *mp;\r
85     uint32_t w_ratio, h_ratio;\r
86     uint32_t stride;\r
87 \r
88     uint32_t daw, dah;\r
89     uint32_t pl;\r
90 \r
91     daw = dah = 0;\r
92             \r
93     mp = msg1;\r
94 \r
95     if(msg->dst.act_w == 0) \r
96     {\r
97         printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__);\r
98         return -EINVAL;\r
99     }\r
100 \r
101     if (msg->dst.act_h == 0)\r
102     {\r
103         printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__);\r
104         return -EINVAL;\r
105     }\r
106     w_ratio = (msg->src.act_w << 16) / msg->dst.act_w;\r
107     h_ratio = (msg->src.act_h << 16) / msg->dst.act_h;\r
108     \r
109     memcpy(msg1, msg, sizeof(struct rga_req));\r
110 \r
111     msg->dst.format = msg->src.format;\r
112 \r
113     /*pre_scale_w cal*/\r
114     if ((w_ratio >= (2<<16)) && (w_ratio < (4<<16))) {            \r
115         daw = (msg->src.act_w + 1) >> 1;\r
116         if((IS_YUV_420(msg->dst.format)) && (daw & 1)) {\r
117             msg->src.act_w = (daw - 1) << 1;                                                    \r
118         }        \r
119     }\r
120     else if ((w_ratio >= (4<<16)) && (w_ratio < (8<<16))) {\r
121         daw = (msg->src.act_w + 3) >> 2;            \r
122         if((IS_YUV_420(msg->dst.format)) && (daw & 1)) {\r
123             msg->src.act_w = (daw - 1) << 2;                                                    \r
124         }\r
125     }\r
126     else if ((w_ratio >= (8<<16)) && (w_ratio < (16<<16))) {\r
127         daw = (msg->src.act_w + 7) >> 3;\r
128         if((IS_YUV_420(msg->dst.format)) && (daw & 1)) {\r
129             msg->src.act_w = (daw - 1) << 3;                                                    \r
130         }\r
131     }\r
132     else\r
133     {\r
134         daw = msg->src.act_w;\r
135     }\r
136 \r
137     pl = (RGA_pixel_width_init(msg->src.format));\r
138     stride = (pl * daw + 3) & (~3);\r
139     msg->dst.act_w = daw;\r
140     msg->dst.vir_w = stride / pl;\r
141 \r
142     /*pre_scale_h cal*/        \r
143     if ((h_ratio >= (2<<16)) && (h_ratio < (4<<16))) {            \r
144         dah = (msg->src.act_h + 1) >> 1;            \r
145         if((IS_YUV(msg->dst.format)) && (dah & 1)) {\r
146             msg->src.act_h = (dah - 1) << 1;                                                    \r
147         }            \r
148     }\r
149     else if ((h_ratio >= (4<<16)) && (h_ratio < (8<<16))) {\r
150         dah = (msg->src.act_h + 3) >> 2;            \r
151         if((IS_YUV(msg->dst.format)) && (dah & 1)) {\r
152             msg->src.act_h = (dah - 1) << 2;                                                    \r
153         }\r
154     }\r
155     else if ((h_ratio >= (8<<16)) && (h_ratio < (16<<16))) {\r
156         dah = (msg->src.act_h + 7) >> 3;\r
157         if((IS_YUV(msg->dst.format)) && (dah & 1)) {\r
158             msg->src.act_h = (dah - 1) << 3;                                                    \r
159         }\r
160     }\r
161     else\r
162     {\r
163         dah = msg->src.act_h;\r
164     }\r
165     \r
166     msg->dst.act_h = dah;\r
167     msg->dst.vir_h = dah;\r
168 \r
169     msg->dst.x_offset = 0;\r
170     msg->dst.y_offset = 0;\r
171             \r
172     msg->dst.yrgb_addr = (u32)rga_service.pre_scale_buf;\r
173     msg->dst.uv_addr = msg->dst.yrgb_addr + stride * dah;\r
174     msg->dst.v_addr = msg->dst.uv_addr + ((stride * dah) >> 1);\r
175 \r
176     msg->render_mode = pre_scaling_mode;\r
177 \r
178     msg1->src.yrgb_addr = msg->dst.yrgb_addr;\r
179     msg1->src.uv_addr = msg->dst.uv_addr;\r
180     msg1->src.v_addr = msg->dst.v_addr;\r
181 \r
182     msg1->src.act_w = msg->dst.act_w;\r
183     msg1->src.act_h = msg->dst.act_h;\r
184     msg1->src.vir_w = msg->dst.vir_w;\r
185     msg1->src.vir_h = msg->dst.vir_h;\r
186             \r
187     return 0;\r
188 }\r
189 \r
190 \r