27 #include <linux/device.h>
29 #include <linux/module.h>
38 #define MIN_RESIZE_VALUE 64
39 #define MID_RESIZE_VALUE 512
40 #define MAX_RESIZE_VALUE 1024
42 #define MIN_IN_WIDTH 32
43 #define MIN_IN_HEIGHT 32
44 #define MAX_IN_WIDTH_MEMORY_MODE 4095
45 #define MAX_IN_WIDTH_ONTHEFLY_MODE_ES1 1280
46 #define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2 4095
47 #define MAX_IN_HEIGHT 4095
49 #define MIN_OUT_WIDTH 16
50 #define MIN_OUT_HEIGHT 2
51 #define MAX_OUT_HEIGHT 4095
57 #define MAX_4TAP_OUT_WIDTH_ES1 1280
58 #define MAX_7TAP_OUT_WIDTH_ES1 640
59 #define MAX_4TAP_OUT_WIDTH_ES2 3312
60 #define MAX_7TAP_OUT_WIDTH_ES2 1650
61 #define MAX_4TAP_OUT_WIDTH_3630 4096
62 #define MAX_7TAP_OUT_WIDTH_3630 2048
67 #define RESIZE_DIVISOR 256
68 #define DEFAULT_PHASE 1
79 0x0000, 0x0100, 0x0000, 0x0000,
80 0x03FA, 0x00F6, 0x0010, 0x0000,
81 0x03F9, 0x00DB, 0x002C, 0x0000,
82 0x03FB, 0x00B3, 0x0053, 0x03FF,
83 0x03FD, 0x0082, 0x0084, 0x03FD,
84 0x03FF, 0x0053, 0x00B3, 0x03FB,
85 0x0000, 0x002C, 0x00DB, 0x03F9,
86 0x0000, 0x0010, 0x00F6, 0x03FA
90 0x0000, 0x0100, 0x0000, 0x0000,
91 0x03FA, 0x00F6, 0x0010, 0x0000,
92 0x03F9, 0x00DB, 0x002C, 0x0000,
93 0x03FB, 0x00B3, 0x0053, 0x03FF,
94 0x03FD, 0x0082, 0x0084, 0x03FD,
95 0x03FF, 0x0053, 0x00B3, 0x03FB,
96 0x0000, 0x002C, 0x00DB, 0x03F9,
97 0x0000, 0x0010, 0x00F6, 0x03FA
102 0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000,
DUMMY,
103 0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000,
DUMMY,
104 0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
105 0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
109 0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000,
DUMMY,
110 0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000,
DUMMY,
111 0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
112 0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
129 static struct v4l2_mbus_framefmt *
134 return v4l2_subdev_get_try_format(fh, pad);
152 return &res->
crop.request;
166 u32 startaddr_h, startaddr_v, tmp_h, tmp_v;
324 const u16 *h_filter, *v_filter;
347 resizer_set_filters(res, h_filter, v_filter);
370 dev_dbg(isp->
dev,
"Output size[w/h]: %dx%d\n", width, height);
434 dev_dbg(isp->
dev,
"Input size[w/h]: %dx%d\n", width, height);
515 unsigned int *max_rate)
522 clock = div_u64((
u64)limit * res->
crop.active.height, ofmt->height);
523 clock =
min(clock, limit / 2);
524 *max_rate = div_u64((
u64)clock * res->
crop.active.width, ofmt->width);
560 unsigned long l3_ick = pipe->
l3_ick;
562 unsigned int cycles_per_frame;
563 unsigned int requests_per_frame;
564 unsigned int cycles_per_request;
592 cycles_per_request = div_u64((
u64)l3_ick / 2 * 256 + pipe->
max_rate - 1,
594 minimum =
DIV_ROUND_UP(cycles_per_request, granularity);
604 * res->
crop.active.height;
605 cycles_per_frame = div_u64((
u64)l3_ick * timeperframe->
numerator,
607 cycles_per_request = cycles_per_frame / requests_per_frame;
611 value =
max(minimum, maximum);
613 dev_dbg(isp->
dev,
"%s: cycles per request = %u\n", __func__, value);
644 __resizer_set_inaddr(res, addr);
668 #define RSZ_PRINT_REGISTER(isp, name)\
669 dev_dbg(isp->dev, "###RSZ " #name "=0x%08x\n", \
670 isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_##name))
676 dev_dbg(isp->
dev,
"-------------Resizer Register dump----------\n");
689 dev_dbg(isp->
dev,
"--------------------------------------------\n");
796 struct v4l2_mbus_framefmt *output,
802 unsigned int upscaled_width;
803 unsigned int upscaled_height;
808 unsigned int width_alignment;
816 min_height = ((input->
height - 7) * 256 - 32 - 64 * spv) / 1024 + 1;
818 max_height = ((input->
height - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1;
820 output->height =
clamp(output->height, min_height, max_height);
822 ratio->
vert = ((input->
height - 4) * 256 + 255 - 16 - 32 * spv)
823 / (output->height - 1);
825 ratio->
vert = ((input->
height - 7) * 256 + 255 - 32 - 64 * spv)
826 / (output->height - 1);
831 upscaled_height = (output->height - 1) * ratio->
vert
833 height = (upscaled_height >> 8) + 4;
835 upscaled_height = (output->height - 1) * ratio->
vert
837 height = (upscaled_height >> 8) + 7;
844 min_width = ((input->
width - 7) * 256 - 32 - 64 * sph) / 1024 + 1;
878 max_width =
min(((input->
width - 7) * 256 + 255 - 16 - 32 * sph) / 64
888 width_alignment = ratio->
vert < 256 ? 8 : 2;
889 output->width =
clamp(output->width, min_width,
890 max_width & ~(width_alignment - 1));
891 output->width =
ALIGN(output->width, width_alignment);
893 ratio->
horz = ((input->
width - 7) * 256 + 255 - 16 - 32 * sph)
894 / (output->width - 1);
896 ratio->
horz = ((input->
width - 7) * 256 + 255 - 32 - 64 * sph)
897 / (output->width - 1);
902 upscaled_width = (output->width - 1) * ratio->
horz
904 width = (upscaled_width >> 8) + 7;
906 upscaled_width = (output->width - 1) * ratio->
horz
908 width = (upscaled_width >> 8) + 7;
926 const struct v4l2_mbus_framefmt *input,
927 const struct v4l2_mbus_framefmt *output)
929 resizer_set_ratio(res, &res->
ratio);
937 resizer_adjust_bandwidth(res);
942 res->
crop.active.left) * 2;
947 resizer_set_start(res, (res->
crop_offset / 2) & 0xf, 0);
953 __resizer_set_inaddr(res,
961 resizer_set_start(res, res->
crop.active.left * 2,
962 res->
crop.active.top);
964 __resizer_set_inaddr(res, 0);
965 resizer_set_input_offset(res, 0);
969 resizer_set_input_size(res, res->
crop.active.width,
970 res->
crop.active.height);
975 struct v4l2_mbus_framefmt *informat, *outformat;
978 resizer_set_source(res, res->
input);
985 resizer_set_input_offset(res, 0);
987 resizer_set_input_offset(res,
ALIGN(informat->width, 0x10) * 2);
991 resizer_set_ycpos(res, informat->code);
993 resizer_set_luma(res, &luma);
996 resizer_set_output_offset(res,
ALIGN(outformat->width * 2, 32));
997 resizer_set_output_size(res, outformat->width, outformat->height);
999 resizer_set_crop_params(res, informat, outformat);
1024 resizer_enable_oneshot(res);
1025 isp_video_dmaqueue_flags_clr(&res->
video_out);
1042 if (buffer !=
NULL) {
1043 resizer_set_outaddr(res, buffer->
isp_addr);
1052 resizer_set_inaddr(res, buffer->
isp_addr);
1057 if (isp_pipeline_ready(pipe))
1065 resizer_enable_oneshot(res);
1077 struct v4l2_mbus_framefmt *informat, *outformat;
1087 resizer_set_crop_params(res, informat, outformat);
1091 resizer_isr_buffer(res);
1098 static int resizer_video_queue(
struct isp_video *video,
1104 resizer_set_inaddr(res, buffer->
isp_addr);
1119 resizer_set_outaddr(res, buffer->
isp_addr);
1125 .queue = resizer_video_queue,
1154 resizer_configure(res);
1155 resizer_print_status(res);
1162 resizer_enable_oneshot(res);
1163 isp_video_dmaqueue_flags_clr(video_out);
1172 resizer_enable_oneshot(res);
1178 dev_dbg(dev,
"%s: module stop timeout.\n", sd->
name);
1182 isp_video_dmaqueue_flags_clr(video_out);
1193 static void resizer_try_crop(
const struct v4l2_mbus_framefmt *
sink,
1194 const struct v4l2_mbus_framefmt *source,
1203 unsigned int min_width =
1204 ((32 * sph + (source->width - 1) * 64 + 16) >> 8) + 7;
1205 unsigned int min_height =
1206 ((32 * spv + (source->height - 1) * 64 + 16) >> 8) + 4;
1207 unsigned int max_width =
1208 ((64 * sph + (source->width - 1) * 1024 + 32) >> 8) + 7;
1209 unsigned int max_height =
1210 ((64 * spv + (source->height - 1) * 1024 + 32) >> 8) + 7;
1218 sink->width - crop->
left);
1221 sink->height - crop->
top);
1234 static int resizer_get_selection(
struct v4l2_subdev *sd,
1236 struct v4l2_subdev_selection *
sel)
1239 struct v4l2_mbus_framefmt *format_source;
1240 struct v4l2_mbus_framefmt *format_sink;
1251 switch (sel->target) {
1258 resizer_try_crop(format_sink, format_source, &sel->r);
1259 resizer_calc_ratios(res, &sel->r, format_source, &ratio);
1263 sel->r = *__resizer_get_crop(res, fh, sel->which);
1264 resizer_calc_ratios(res, &sel->r, format_source, &ratio);
1287 static int resizer_set_selection(
struct v4l2_subdev *sd,
1289 struct v4l2_subdev_selection *sel)
1293 struct v4l2_mbus_framefmt *format_sink, *format_source;
1305 dev_dbg(isp->
dev,
"%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
1306 sel->r.left, sel->r.top, sel->r.width, sel->r.height,
1309 dev_dbg(isp->
dev,
"%s: input=%dx%d, output=%dx%d\n", __func__,
1310 format_sink->width, format_sink->height,
1311 format_source->width, format_source->height);
1321 resizer_try_crop(format_sink, format_source, &sel->r);
1322 *__resizer_get_crop(res, fh, sel->which) = sel->r;
1323 resizer_calc_ratios(res, &sel->r, format_source, &ratio);
1329 res->
crop.active = sel->r;
1342 static const unsigned int resizer_formats[] = {
1347 static unsigned int resizer_max_in_width(
struct isp_res_device *res)
1371 struct v4l2_mbus_framefmt *
fmt,
1374 struct v4l2_mbus_framefmt *
format;
1385 resizer_max_in_width(res));
1391 format = __resizer_get_format(res, fh,
RESZ_PAD_SINK, which);
1392 fmt->code = format->code;
1394 crop = *__resizer_get_crop(res, fh, which);
1395 resizer_calc_ratios(res, &crop, fmt, &ratio);
1410 static int resizer_enum_mbus_code(
struct v4l2_subdev *sd,
1412 struct v4l2_subdev_mbus_code_enum *
code)
1415 struct v4l2_mbus_framefmt *
format;
1418 if (code->index >=
ARRAY_SIZE(resizer_formats))
1421 code->code = resizer_formats[code->index];
1423 if (code->index != 0)
1428 code->code = format->code;
1434 static int resizer_enum_frame_size(
struct v4l2_subdev *sd,
1436 struct v4l2_subdev_frame_size_enum *fse)
1439 struct v4l2_mbus_framefmt format;
1441 if (fse->index != 0)
1444 format.code = fse->code;
1448 fse->min_width = format.width;
1449 fse->min_height = format.height;
1451 if (format.code != fse->code)
1454 format.code = fse->code;
1458 fse->max_width = format.width;
1459 fse->max_height = format.height;
1475 struct v4l2_mbus_framefmt *
format;
1477 format = __resizer_get_format(res, fh, fmt->
pad, fmt->
which);
1496 struct v4l2_mbus_framefmt *
format;
1499 format = __resizer_get_format(res, fh, fmt->
pad, fmt->
which);
1508 crop = __resizer_get_crop(res, fh, fmt->
which);
1527 res->
crop.active = res->
crop.request;
1528 resizer_calc_ratios(res, &res->
crop.active, format,
1544 static int resizer_init_formats(
struct v4l2_subdev *sd,
1549 memset(&format, 0,
sizeof(format));
1553 format.format.width = 4096;
1554 format.format.height = 4096;
1555 resizer_set_format(sd, fh, &format);
1562 .s_stream = resizer_set_stream,
1567 .enum_mbus_code = resizer_enum_mbus_code,
1568 .enum_frame_size = resizer_enum_frame_size,
1569 .get_fmt = resizer_get_format,
1570 .set_fmt = resizer_set_format,
1571 .get_selection = resizer_get_selection,
1572 .set_selection = resizer_set_selection,
1577 .video = &resizer_v4l2_video_ops,
1578 .pad = &resizer_v4l2_pad_ops,
1583 .open = resizer_init_formats,
1598 static int resizer_link_setup(
struct media_entity *entity,
1605 switch (local->
index | media_entity_type(remote->
entity)) {
1620 if (flags & MEDIA_LNK_FL_ENABLED) {
1643 .link_setup = resizer_link_setup,
1644 .link_validate = v4l2_subdev_link_validate,
1701 v4l2_set_subdevdata(sd, res);
1707 me->
ops = &resizer_media_ops;
1712 resizer_init_formats(sd,
NULL);
1715 res->
video_in.ops = &resizer_video_ops;
1720 res->
video_out.ops = &resizer_video_ops;
1727 goto error_video_in;
1731 goto error_video_out;
1768 return resizer_init_entities(res);