Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: aspeed: Support aspeed mode to reduce compressed data

aspeed supports differential jpeg format which only compress the parts
which are changed. In this way, it reduces both the amount of data to be
transferred by network and those to be decoded on the client side.

2 new ctrls are added:
* Aspeed HQ Mode: to control aspeed's high quality(2-pass) compression mode
This only works with yuv444 subsampling.
* Aspeed HQ Quality: to control the quality of aspeed's HQ mode
only useful if Aspeed HQ mode is enabled

Aspeed JPEG Format requires an additional buffer, called bcd, to store
the information about which macro block in the new frame is different
from the previous one.

To have bcd correctly working, we need to swap the buffers for src0/1 to
make src1 refer to previous frame and src0 to the coming new frame.

Signed-off-by: Jammy Huang <jammy_huang@aspeedtech.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
[hverkuil: fix logging dma_addr_t, use %pad for that]

authored by

Jammy Huang and committed by
Hans Verkuil
d4b9fd00 dae86bb6

+241 -51
+227 -51
drivers/media/platform/aspeed/aspeed-video.c
··· 33 33 #include <media/v4l2-event.h> 34 34 #include <media/v4l2-ioctl.h> 35 35 #include <media/videobuf2-dma-contig.h> 36 + #include <uapi/linux/aspeed-video.h> 36 37 37 38 #define ASPEED_VIDEO_V4L2_MIN_BUF_REQ 3 38 39 ··· 60 59 61 60 #define VE_MAX_SRC_BUFFER_SIZE 0x8ca000 /* 1920 * 1200, 32bpp */ 62 61 #define VE_JPEG_HEADER_SIZE 0x006000 /* 512 * 12 * 4 */ 62 + #define VE_BCD_BUFF_SIZE 0x9000 /* (1920/8) * (1200/8) */ 63 63 64 64 #define VE_PROTECTION_KEY 0x000 65 65 #define VE_PROTECTION_KEY_UNLOCK 0x1a038aa8 ··· 109 107 #define VE_SCALING_FILTER2 0x020 110 108 #define VE_SCALING_FILTER3 0x024 111 109 110 + #define VE_BCD_CTRL 0x02C 111 + #define VE_BCD_CTRL_EN_BCD BIT(0) 112 + #define VE_BCD_CTRL_EN_ABCD BIT(1) 113 + #define VE_BCD_CTRL_EN_CB BIT(2) 114 + #define VE_BCD_CTRL_THR GENMASK(23, 16) 115 + #define VE_BCD_CTRL_ABCD_THR GENMASK(31, 24) 116 + 112 117 #define VE_CAP_WINDOW 0x030 113 118 #define VE_COMP_WINDOW 0x034 114 119 #define VE_COMP_PROC_OFFSET 0x038 ··· 124 115 #define VE_SRC0_ADDR 0x044 125 116 #define VE_SRC_SCANLINE_OFFSET 0x048 126 117 #define VE_SRC1_ADDR 0x04c 118 + #define VE_BCD_ADDR 0x050 127 119 #define VE_COMP_ADDR 0x054 128 120 129 121 #define VE_STREAM_BUF_SIZE 0x058 ··· 144 134 #define VE_COMP_CTRL_ENCODE GENMASK(21, 20) 145 135 #define VE_COMP_CTRL_HQ_DCT_CHR GENMASK(26, 22) 146 136 #define VE_COMP_CTRL_HQ_DCT_LUM GENMASK(31, 27) 137 + 138 + #define VE_CB_ADDR 0x06C 147 139 148 140 #define AST2400_VE_COMP_SIZE_READ_BACK 0x078 149 141 #define AST2600_VE_COMP_SIZE_READ_BACK 0x084 ··· 223 211 VIDEO_CLOCKS_ON, 224 212 }; 225 213 214 + enum aspeed_video_format { 215 + VIDEO_FMT_STANDARD = 0, 216 + VIDEO_FMT_ASPEED, 217 + VIDEO_FMT_MAX = VIDEO_FMT_ASPEED 218 + }; 219 + 226 220 // for VE_CTRL_CAPTURE_FMT 227 221 enum aspeed_video_capture_format { 228 222 VIDEO_CAP_FMT_YUV_STUDIO_SWING = 0, ··· 263 245 /* 264 246 * struct aspeed_video - driver data 265 247 * 266 - * res_work: holds the delayed_work for res-detection if unlock 267 - * buffers: holds the list of buffer queued from user 248 + * res_work: holds the delayed_work for res-detection if unlock 249 + * buffers: holds the list of buffer queued from user 268 250 * flags: holds the state of video 269 251 * sequence: holds the last number of frame completed 270 252 * max_compressed_size: holds max compressed stream's size 271 253 * srcs: holds the buffer information for srcs 272 254 * jpeg: holds the buffer information for jpeg header 255 + * bcd: holds the buffer information for bcd work 273 256 * yuv420: a flag raised if JPEG subsampling is 420 257 + * format: holds the video format 258 + * hq_mode: a flag raised if HQ is enabled. Only for VIDEO_FMT_ASPEED 274 259 * frame_rate: holds the frame_rate 275 260 * jpeg_quality: holds jpeq's quality (0~11) 261 + * jpeg_hq_quality: holds hq's quality (1~12) only if hq_mode enabled 276 262 * frame_bottom: end position of video data in vertical direction 277 263 * frame_left: start position of video data in horizontal direction 278 264 * frame_right: end position of video data in horizontal direction ··· 312 290 unsigned int max_compressed_size; 313 291 struct aspeed_video_addr srcs[2]; 314 292 struct aspeed_video_addr jpeg; 293 + struct aspeed_video_addr bcd; 315 294 316 295 bool yuv420; 296 + enum aspeed_video_format format; 297 + bool hq_mode; 317 298 unsigned int frame_rate; 318 299 unsigned int jpeg_quality; 300 + unsigned int jpeg_hq_quality; 319 301 320 302 unsigned int frame_bottom; 321 303 unsigned int frame_left; ··· 484 458 }, 485 459 }; 486 460 461 + static const char * const format_str[] = {"Standard JPEG", 462 + "Aspeed JPEG"}; 463 + 487 464 static unsigned int debug; 465 + 466 + static bool aspeed_video_alloc_buf(struct aspeed_video *video, 467 + struct aspeed_video_addr *addr, 468 + unsigned int size); 469 + 470 + static void aspeed_video_free_buf(struct aspeed_video *video, 471 + struct aspeed_video_addr *addr); 488 472 489 473 static void aspeed_video_init_jpeg_table(u32 *table, bool yuv420) 490 474 { ··· 583 547 unsigned long flags; 584 548 struct aspeed_video_buffer *buf; 585 549 u32 seq_ctrl = aspeed_video_read(video, VE_SEQ_CTRL); 550 + bool bcd_buf_need = (video->format != VIDEO_FMT_STANDARD); 586 551 587 552 if (video->v4l2_input_status) { 588 553 v4l2_warn(&video->v4l2_dev, "No signal; don't start frame\n"); ··· 594 557 !(seq_ctrl & VE_SEQ_CTRL_CAP_BUSY)) { 595 558 v4l2_warn(&video->v4l2_dev, "Engine busy; don't start frame\n"); 596 559 return -EBUSY; 560 + } 561 + 562 + if (bcd_buf_need && !video->bcd.size) { 563 + if (!aspeed_video_alloc_buf(video, &video->bcd, 564 + VE_BCD_BUFF_SIZE)) { 565 + dev_err(video->dev, "Failed to allocate BCD buffer\n"); 566 + dev_err(video->dev, "don't start frame\n"); 567 + return -ENOMEM; 568 + } 569 + aspeed_video_write(video, VE_BCD_ADDR, video->bcd.dma); 570 + v4l2_dbg(1, debug, &video->v4l2_dev, "bcd addr(%pad) size(%d)\n", 571 + &video->bcd.dma, video->bcd.size); 572 + } else if (!bcd_buf_need && video->bcd.size) { 573 + aspeed_video_free_buf(video, &video->bcd); 597 574 } 598 575 599 576 spin_lock_irqsave(&video->lock, flags); ··· 708 657 schedule_delayed_work(&video->res_work, delay); 709 658 } 710 659 660 + static void aspeed_video_swap_src_buf(struct aspeed_video *v) 661 + { 662 + if (v->format == VIDEO_FMT_STANDARD) 663 + return; 664 + 665 + /* Reset bcd buffer to have a full frame update every 8 frames. */ 666 + if (IS_ALIGNED(v->sequence, 8)) 667 + memset((u8 *)v->bcd.virt, 0x00, VE_BCD_BUFF_SIZE); 668 + 669 + if (v->sequence & 0x01) { 670 + aspeed_video_write(v, VE_SRC0_ADDR, v->srcs[1].dma); 671 + aspeed_video_write(v, VE_SRC1_ADDR, v->srcs[0].dma); 672 + } else { 673 + aspeed_video_write(v, VE_SRC0_ADDR, v->srcs[0].dma); 674 + aspeed_video_write(v, VE_SRC1_ADDR, v->srcs[1].dma); 675 + } 676 + } 677 + 711 678 static irqreturn_t aspeed_video_irq(int irq, void *arg) 712 679 { 713 680 struct aspeed_video *video = arg; ··· 774 705 775 706 if (sts & VE_INTERRUPT_COMP_COMPLETE) { 776 707 struct aspeed_video_buffer *buf; 708 + bool empty = true; 777 709 u32 frame_size = aspeed_video_read(video, 778 710 video->comp_size_read); 779 711 ··· 788 718 if (buf) { 789 719 vb2_set_plane_payload(&buf->vb.vb2_buf, 0, frame_size); 790 720 791 - if (!list_is_last(&buf->link, &video->buffers)) { 721 + /* 722 + * aspeed_jpeg requires continuous update. 723 + * On the contrary, standard jpeg can keep last buffer 724 + * to always have the latest result. 725 + */ 726 + if (video->format == VIDEO_FMT_STANDARD && 727 + list_is_last(&buf->link, &video->buffers)) { 728 + empty = false; 729 + v4l2_warn(&video->v4l2_dev, "skip to keep last frame updated\n"); 730 + } else { 792 731 buf->vb.vb2_buf.timestamp = ktime_get_ns(); 793 732 buf->vb.sequence = video->sequence++; 794 733 buf->vb.field = V4L2_FIELD_NONE; 795 734 vb2_buffer_done(&buf->vb.vb2_buf, 796 735 VB2_BUF_STATE_DONE); 797 736 list_del(&buf->link); 737 + empty = list_empty(&video->buffers); 798 738 } 799 739 } 800 740 spin_unlock(&video->lock); ··· 818 738 aspeed_video_write(video, VE_INTERRUPT_STATUS, 819 739 VE_INTERRUPT_COMP_COMPLETE); 820 740 sts &= ~VE_INTERRUPT_COMP_COMPLETE; 821 - if (test_bit(VIDEO_STREAMING, &video->flags) && buf) 741 + 742 + aspeed_video_swap_src_buf(video); 743 + 744 + if (test_bit(VIDEO_STREAMING, &video->flags) && !empty) 822 745 aspeed_video_start_frame(video); 823 746 } 824 747 ··· 1168 1085 FIELD_PREP(VE_TGS_FIRST, video->frame_top) | 1169 1086 FIELD_PREP(VE_TGS_LAST, 1170 1087 video->frame_bottom + 1)); 1171 - aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_INT_DE); 1088 + aspeed_video_update(video, VE_CTRL, 1089 + VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH, 1090 + VE_CTRL_INT_DE); 1172 1091 } else { 1173 1092 v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Direct Mode\n"); 1174 - aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_DIRECT_FETCH); 1093 + aspeed_video_update(video, VE_CTRL, 1094 + VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH, 1095 + VE_CTRL_DIRECT_FETCH); 1175 1096 } 1176 1097 1177 1098 size *= 4; ··· 1208 1121 aspeed_video_free_buf(video, &video->srcs[0]); 1209 1122 } 1210 1123 1211 - static void aspeed_video_init_regs(struct aspeed_video *video) 1124 + static void aspeed_video_update_regs(struct aspeed_video *video) 1212 1125 { 1213 - u32 comp_ctrl = VE_COMP_CTRL_RSVD | 1214 - FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) | 1215 - FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10); 1216 - u32 ctrl = VE_CTRL_AUTO_OR_CURSOR | 1217 - FIELD_PREP(VE_CTRL_CAPTURE_FMT, VIDEO_CAP_FMT_YUV_FULL_SWING); 1218 - u32 seq_ctrl = video->jpeg_mode; 1126 + u8 jpeg_hq_quality = clamp((int)video->jpeg_hq_quality - 1, 0, 1127 + ASPEED_VIDEO_JPEG_NUM_QUALITIES - 1); 1128 + u32 comp_ctrl = FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) | 1129 + FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10) | 1130 + FIELD_PREP(VE_COMP_CTRL_EN_HQ, video->hq_mode) | 1131 + FIELD_PREP(VE_COMP_CTRL_HQ_DCT_LUM, jpeg_hq_quality) | 1132 + FIELD_PREP(VE_COMP_CTRL_HQ_DCT_CHR, jpeg_hq_quality | 0x10); 1133 + u32 ctrl = 0; 1134 + u32 seq_ctrl = 0; 1135 + 1136 + v4l2_dbg(1, debug, &video->v4l2_dev, "framerate(%d)\n", 1137 + video->frame_rate); 1138 + v4l2_dbg(1, debug, &video->v4l2_dev, "jpeg format(%s) subsample(%s)\n", 1139 + format_str[video->format], 1140 + video->yuv420 ? "420" : "444"); 1141 + v4l2_dbg(1, debug, &video->v4l2_dev, "compression quality(%d)\n", 1142 + video->jpeg_quality); 1143 + v4l2_dbg(1, debug, &video->v4l2_dev, "hq_mode(%s) hq_quality(%d)\n", 1144 + video->hq_mode ? "on" : "off", video->jpeg_hq_quality); 1145 + 1146 + if (video->format == VIDEO_FMT_ASPEED) 1147 + aspeed_video_update(video, VE_BCD_CTRL, 0, VE_BCD_CTRL_EN_BCD); 1148 + else 1149 + aspeed_video_update(video, VE_BCD_CTRL, VE_BCD_CTRL_EN_BCD, 0); 1219 1150 1220 1151 if (video->frame_rate) 1221 1152 ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate); 1222 1153 1154 + if (video->format == VIDEO_FMT_STANDARD) { 1155 + comp_ctrl &= ~FIELD_PREP(VE_COMP_CTRL_EN_HQ, video->hq_mode); 1156 + seq_ctrl |= video->jpeg_mode; 1157 + } 1158 + 1223 1159 if (video->yuv420) 1224 1160 seq_ctrl |= VE_SEQ_CTRL_YUV420; 1161 + 1162 + if (video->jpeg.virt) 1163 + aspeed_video_update_jpeg_table(video->jpeg.virt, video->yuv420); 1164 + 1165 + /* Set control registers */ 1166 + aspeed_video_update(video, VE_SEQ_CTRL, 1167 + video->jpeg_mode | VE_SEQ_CTRL_YUV420, 1168 + seq_ctrl); 1169 + aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC, ctrl); 1170 + aspeed_video_update(video, VE_COMP_CTRL, 1171 + VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR | 1172 + VE_COMP_CTRL_EN_HQ | VE_COMP_CTRL_HQ_DCT_LUM | 1173 + VE_COMP_CTRL_HQ_DCT_CHR | VE_COMP_CTRL_VQ_4COLOR | 1174 + VE_COMP_CTRL_VQ_DCT_ONLY, 1175 + comp_ctrl); 1176 + } 1177 + 1178 + static void aspeed_video_init_regs(struct aspeed_video *video) 1179 + { 1180 + u32 ctrl = VE_CTRL_AUTO_OR_CURSOR | 1181 + FIELD_PREP(VE_CTRL_CAPTURE_FMT, VIDEO_CAP_FMT_YUV_FULL_SWING); 1225 1182 1226 1183 /* Unlock VE registers */ 1227 1184 aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_UNLOCK); ··· 1281 1150 aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma); 1282 1151 1283 1152 /* Set control registers */ 1284 - aspeed_video_write(video, VE_SEQ_CTRL, seq_ctrl); 1285 1153 aspeed_video_write(video, VE_CTRL, ctrl); 1286 - aspeed_video_write(video, VE_COMP_CTRL, comp_ctrl); 1154 + aspeed_video_write(video, VE_COMP_CTRL, VE_COMP_CTRL_RSVD); 1287 1155 1288 1156 /* Don't downscale */ 1289 1157 aspeed_video_write(video, VE_SCALING_FACTOR, 0x10001000); ··· 1298 1168 FIELD_PREP(VE_MODE_DT_HOR_STABLE, 6) | 1299 1169 FIELD_PREP(VE_MODE_DT_VER_STABLE, 6) | 1300 1170 FIELD_PREP(VE_MODE_DT_EDG_THROD, 0x65)); 1171 + 1172 + aspeed_video_write(video, VE_BCD_CTRL, 0); 1301 1173 } 1302 1174 1303 1175 static void aspeed_video_start(struct aspeed_video *video) ··· 1333 1201 if (video->srcs[1].size) 1334 1202 aspeed_video_free_buf(video, &video->srcs[1]); 1335 1203 1204 + if (video->bcd.size) 1205 + aspeed_video_free_buf(video, &video->bcd); 1206 + 1336 1207 video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; 1337 1208 video->flags = 0; 1338 1209 } ··· 1354 1219 static int aspeed_video_enum_format(struct file *file, void *fh, 1355 1220 struct v4l2_fmtdesc *f) 1356 1221 { 1222 + struct aspeed_video *video = video_drvdata(file); 1223 + 1357 1224 if (f->index) 1358 1225 return -EINVAL; 1359 1226 1360 - f->pixelformat = V4L2_PIX_FMT_JPEG; 1227 + f->pixelformat = video->pix_fmt.pixelformat; 1361 1228 1362 1229 return 0; 1363 1230 } ··· 1370 1233 struct aspeed_video *video = video_drvdata(file); 1371 1234 1372 1235 f->fmt.pix = video->pix_fmt; 1236 + 1237 + return 0; 1238 + } 1239 + 1240 + static int aspeed_video_set_format(struct file *file, void *fh, 1241 + struct v4l2_format *f) 1242 + { 1243 + struct aspeed_video *video = video_drvdata(file); 1244 + 1245 + if (vb2_is_busy(&video->queue)) 1246 + return -EBUSY; 1247 + 1248 + switch (f->fmt.pix.pixelformat) { 1249 + case V4L2_PIX_FMT_JPEG: 1250 + video->format = VIDEO_FMT_STANDARD; 1251 + break; 1252 + case V4L2_PIX_FMT_AJPG: 1253 + video->format = VIDEO_FMT_ASPEED; 1254 + break; 1255 + default: 1256 + return -EINVAL; 1257 + } 1258 + video->pix_fmt.pixelformat = f->fmt.pix.pixelformat; 1373 1259 1374 1260 return 0; 1375 1261 } ··· 1614 1454 1615 1455 .vidioc_enum_fmt_vid_cap = aspeed_video_enum_format, 1616 1456 .vidioc_g_fmt_vid_cap = aspeed_video_get_format, 1617 - .vidioc_s_fmt_vid_cap = aspeed_video_get_format, 1457 + .vidioc_s_fmt_vid_cap = aspeed_video_set_format, 1618 1458 .vidioc_try_fmt_vid_cap = aspeed_video_get_format, 1619 1459 1620 1460 .vidioc_reqbufs = vb2_ioctl_reqbufs, ··· 1646 1486 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1647 1487 }; 1648 1488 1649 - static void aspeed_video_update_jpeg_quality(struct aspeed_video *video) 1650 - { 1651 - u32 comp_ctrl = FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) | 1652 - FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10); 1653 - 1654 - aspeed_video_update(video, VE_COMP_CTRL, 1655 - VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR, 1656 - comp_ctrl); 1657 - } 1658 - 1659 - static void aspeed_video_update_subsampling(struct aspeed_video *video) 1660 - { 1661 - if (video->jpeg.virt) 1662 - aspeed_video_update_jpeg_table(video->jpeg.virt, video->yuv420); 1663 - 1664 - if (video->yuv420) 1665 - aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420); 1666 - else 1667 - aspeed_video_update(video, VE_SEQ_CTRL, VE_SEQ_CTRL_YUV420, 0); 1668 - } 1669 - 1670 1489 static int aspeed_video_set_ctrl(struct v4l2_ctrl *ctrl) 1671 1490 { 1672 1491 struct aspeed_video *video = container_of(ctrl->handler, ··· 1655 1516 switch (ctrl->id) { 1656 1517 case V4L2_CID_JPEG_COMPRESSION_QUALITY: 1657 1518 video->jpeg_quality = ctrl->val; 1658 - aspeed_video_update_jpeg_quality(video); 1519 + if (test_bit(VIDEO_STREAMING, &video->flags)) 1520 + aspeed_video_update_regs(video); 1659 1521 break; 1660 1522 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: 1661 - if (ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_420) { 1662 - video->yuv420 = true; 1663 - aspeed_video_update_subsampling(video); 1664 - } else { 1665 - video->yuv420 = false; 1666 - aspeed_video_update_subsampling(video); 1667 - } 1523 + video->yuv420 = (ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_420); 1524 + if (test_bit(VIDEO_STREAMING, &video->flags)) 1525 + aspeed_video_update_regs(video); 1526 + break; 1527 + case V4L2_CID_ASPEED_HQ_MODE: 1528 + video->hq_mode = ctrl->val; 1529 + if (test_bit(VIDEO_STREAMING, &video->flags)) 1530 + aspeed_video_update_regs(video); 1531 + break; 1532 + case V4L2_CID_ASPEED_HQ_JPEG_QUALITY: 1533 + video->jpeg_hq_quality = ctrl->val; 1534 + if (test_bit(VIDEO_STREAMING, &video->flags)) 1535 + aspeed_video_update_regs(video); 1668 1536 break; 1669 1537 default: 1670 1538 return -EINVAL; ··· 1682 1536 1683 1537 static const struct v4l2_ctrl_ops aspeed_video_ctrl_ops = { 1684 1538 .s_ctrl = aspeed_video_set_ctrl, 1539 + }; 1540 + 1541 + static const struct v4l2_ctrl_config aspeed_ctrl_HQ_mode = { 1542 + .ops = &aspeed_video_ctrl_ops, 1543 + .id = V4L2_CID_ASPEED_HQ_MODE, 1544 + .name = "Aspeed HQ Mode", 1545 + .type = V4L2_CTRL_TYPE_BOOLEAN, 1546 + .min = false, 1547 + .max = true, 1548 + .step = 1, 1549 + .def = false, 1550 + }; 1551 + 1552 + static const struct v4l2_ctrl_config aspeed_ctrl_HQ_jpeg_quality = { 1553 + .ops = &aspeed_video_ctrl_ops, 1554 + .id = V4L2_CID_ASPEED_HQ_JPEG_QUALITY, 1555 + .name = "Aspeed HQ Quality", 1556 + .type = V4L2_CTRL_TYPE_INTEGER, 1557 + .min = 1, 1558 + .max = ASPEED_VIDEO_JPEG_NUM_QUALITIES, 1559 + .step = 1, 1560 + .def = 1, 1685 1561 }; 1686 1562 1687 1563 static void aspeed_video_resolution_work(struct work_struct *work) ··· 1719 1551 goto done; 1720 1552 1721 1553 aspeed_video_init_regs(video); 1554 + 1555 + aspeed_video_update_regs(video); 1722 1556 1723 1557 aspeed_video_get_resolution(video); 1724 1558 ··· 1831 1661 video->sequence = 0; 1832 1662 video->perf.duration_max = 0; 1833 1663 video->perf.duration_min = 0xffffffff; 1664 + 1665 + aspeed_video_update_regs(video); 1834 1666 1835 1667 rc = aspeed_video_start_frame(video); 1836 1668 if (rc) { ··· 1972 1800 struct v4l2_device *v4l2_dev = &video->v4l2_dev; 1973 1801 struct vb2_queue *vbq = &video->queue; 1974 1802 struct video_device *vdev = &video->vdev; 1803 + struct v4l2_ctrl_handler *hdl = &video->ctrl_handler; 1975 1804 int rc; 1976 1805 1977 1806 video->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG; ··· 1987 1814 return rc; 1988 1815 } 1989 1816 1990 - v4l2_ctrl_handler_init(&video->ctrl_handler, 2); 1991 - v4l2_ctrl_new_std(&video->ctrl_handler, &aspeed_video_ctrl_ops, 1817 + v4l2_ctrl_handler_init(hdl, 4); 1818 + v4l2_ctrl_new_std(hdl, &aspeed_video_ctrl_ops, 1992 1819 V4L2_CID_JPEG_COMPRESSION_QUALITY, 0, 1993 1820 ASPEED_VIDEO_JPEG_NUM_QUALITIES - 1, 1, 0); 1994 - v4l2_ctrl_new_std_menu(&video->ctrl_handler, &aspeed_video_ctrl_ops, 1821 + v4l2_ctrl_new_std_menu(hdl, &aspeed_video_ctrl_ops, 1995 1822 V4L2_CID_JPEG_CHROMA_SUBSAMPLING, 1996 1823 V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask, 1997 1824 V4L2_JPEG_CHROMA_SUBSAMPLING_444); 1825 + v4l2_ctrl_new_custom(hdl, &aspeed_ctrl_HQ_mode, NULL); 1826 + v4l2_ctrl_new_custom(hdl, &aspeed_ctrl_HQ_jpeg_quality, NULL); 1998 1827 1999 - rc = video->ctrl_handler.error; 1828 + rc = hdl->error; 2000 1829 if (rc) { 2001 1830 v4l2_ctrl_handler_free(&video->ctrl_handler); 2002 1831 v4l2_device_unregister(v4l2_dev); ··· 2007 1832 return rc; 2008 1833 } 2009 1834 2010 - v4l2_dev->ctrl_handler = &video->ctrl_handler; 1835 + v4l2_dev->ctrl_handler = hdl; 2011 1836 2012 1837 vbq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2013 1838 vbq->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; ··· 2155 1980 video->comp_size_read = config->comp_size_read; 2156 1981 2157 1982 video->frame_rate = 30; 1983 + video->jpeg_hq_quality = 1; 2158 1984 video->dev = &pdev->dev; 2159 1985 spin_lock_init(&video->lock); 2160 1986 mutex_init(&video->video_lock);
+14
include/uapi/linux/aspeed-video.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ 2 + /* 3 + * Copyright (C) 2021 ASPEED Technology Inc. 4 + */ 5 + 6 + #ifndef _UAPI_LINUX_ASPEED_VIDEO_H 7 + #define _UAPI_LINUX_ASPEED_VIDEO_H 8 + 9 + #include <linux/v4l2-controls.h> 10 + 11 + #define V4L2_CID_ASPEED_HQ_MODE (V4L2_CID_USER_ASPEED_BASE + 1) 12 + #define V4L2_CID_ASPEED_HQ_JPEG_QUALITY (V4L2_CID_USER_ASPEED_BASE + 2) 13 + 14 + #endif /* _UAPI_LINUX_ASPEED_VIDEO_H */