11a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* 21a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil yuv support 31a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 41a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Copyright (C) 2007 Ian Armstrong <ian@iarmst.demon.co.uk> 51a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 61a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil This program is free software; you can redistribute it and/or modify 71a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil it under the terms of the GNU General Public License as published by 81a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil the Free Software Foundation; either version 2 of the License, or 91a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil (at your option) any later version. 101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil This program is distributed in the hope that it will be useful, 121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil but WITHOUT ANY WARRANTY; without even the implied warranty of 131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil GNU General Public License for more details. 151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil You should have received a copy of the GNU General Public License 171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil along with this program; if not, write to the Free Software 181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil */ 201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include "ivtv-driver.h" 221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil#include "ivtv-udma.h" 2383df8e7b0d7b319f9ce9773eaf4b1da324ae17d7Hans Verkuil#include "ivtv-yuv.h" 241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 25a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong/* YUV buffer offsets */ 26a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrongconst u32 yuv_offset[IVTV_YUV_BUFFERS] = { 27a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x001a8600, 28a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x00240400, 29a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x002d8200, 30a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x00370000, 31a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x00029000, 32a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x000C0E00, 33a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x006B0400, 34a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 0x00748200 35612570f2c4794bbf4e5bfa8648b61fbfc9cd8501Hans Verkuil}; 36612570f2c4794bbf4e5bfa8648b61fbfc9cd8501Hans Verkuil 371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, 382b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong struct ivtv_dma_frame *args) 391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 401a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil struct ivtv_dma_page_info y_dma; 411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil struct ivtv_dma_page_info uv_dma; 423b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 433b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong u8 frame = yi->draw_frame; 443b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_frame_info *f = &yi->new_frame_info[frame]; 451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int i; 461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int y_pages, uv_pages; 471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil unsigned long y_buffer_offset, uv_buffer_offset; 481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int y_decode_height, uv_decode_height, y_size; 491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5033c0fcad2160bc211272295e862c6f708118d006Hans Verkuil y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame]; 511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; 521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 532b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong y_decode_height = uv_decode_height = f->src_h + f->src_y; 541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 553b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (f->offset_y) 561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil y_buffer_offset += 720 * 16; 571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (y_decode_height & 15) 591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil y_decode_height = (y_decode_height + 16) & ~15; 601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (uv_decode_height & 31) 621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil uv_decode_height = (uv_decode_height + 32) & ~31; 631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil y_size = 720 * y_decode_height; 651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Still in USE */ 671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (dma->SG_length || dma->page_count) { 682b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_WARN 692b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ("prep_user_dma: SG_length %d page_count %d still full?\n", 702b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong dma->SG_length, dma->page_count); 711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return -EBUSY; 721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height); 751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height); 761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Get user pages for DMA Xfer */ 781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil down_read(¤t->mm->mmap_sem); 791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL); 807fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella uv_pages = 0; /* silence gcc. value is set and consumed only if: */ 817fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella if (y_pages == y_dma.page_count) { 827fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella uv_pages = get_user_pages(current, current->mm, 837fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella uv_dma.uaddr, uv_dma.page_count, 0, 1, 847fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella &dma->map[y_pages], NULL); 857fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella } 861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil up_read(¤t->mm->mmap_sem); 871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 887fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) { 897fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella int rc = -EFAULT; 907fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella 917fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella if (y_pages == y_dma.page_count) { 927fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella IVTV_DEBUG_WARN 937fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella ("failed to map uv user pages, returned %d " 947fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella "expecting %d\n", uv_pages, uv_dma.page_count); 957fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella 967fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella if (uv_pages >= 0) { 977fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella for (i = 0; i < uv_pages; i++) 987fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella put_page(dma->map[y_pages + i]); 997fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella rc = -EFAULT; 1007fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella } else { 1017fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella rc = uv_pages; 1027fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella } 1037fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella } else { 1047fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella IVTV_DEBUG_WARN 1057fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella ("failed to map y user pages, returned %d " 1067fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella "expecting %d\n", y_pages, y_dma.page_count); 1071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1087fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella if (y_pages >= 0) { 1097fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella for (i = 0; i < y_pages; i++) 1107fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella put_page(dma->map[i]); 1117fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella /* 1127fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella * Inherit the -EFAULT from rc's 1137fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella * initialization, but allow it to be 1147fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella * overriden by uv_pages above if it was an 1157fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella * actual errno. 1167fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella */ 1177fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella } else { 1187fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella rc = y_pages; 1197fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella } 1207fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella return rc; 1211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1237fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella dma->page_count = y_pages + uv_pages; 1247fd4b41f053681cccf188cc1731ae43fe38fa969Paul Cassella 1251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Fill & map SG List */ 1268beb058f1ecde7bc0554d18ce1baa18b5dfb02d3Hans Verkuil if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) { 1270989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n"); 1280989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil for (i = 0; i < dma->page_count; i++) { 1290989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil put_page(dma->map[i]); 1300989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil } 1310989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil dma->page_count = 0; 1320989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil return -ENOMEM; 1330989fd2c88a11aa5014b2b348ed51872d14d536dHans Verkuil } 1348ac05ae3192ce8a71fc84e4a88772cce0c09173cHans Verkuil dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); 1351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Fill SG Array with new values */ 1372b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size); 1381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* If we've offset the y plane, ensure top area is blanked */ 1402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->offset_y && yi->blanking_dmaptr) { 1413b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); 1422b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr); 1433b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]); 1443b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong dma->SG_length++; 1451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Tag SG Array with Interrupt Bit */ 1481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000); 1491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil ivtv_udma_sync_for_device(itv); 1511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return 0; 1521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 1531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* We rely on a table held in the firmware - Quick check. */ 1551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilint ivtv_yuv_filter_check(struct ivtv *itv) 1561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 1572b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong int i, y, uv; 1581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1592b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) { 1602b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) || 1612b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) { 1621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil IVTV_WARN ("YUV filter table not found in firmware.\n"); 1631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return -1; 1641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return 0; 1671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 1681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilstatic void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2) 1701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 1712b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong u32 i, line; 1721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* If any filter is -1, then don't update it */ 1741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (h_filter > -1) { 1752b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (h_filter > 4) 1762b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong h_filter = 4; 1772b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384); 1782b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong for (line = 0; line < 16; line++) { 1792b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02804); 1802b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x0281c); 1812b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 4; 1822b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02808); 1832b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02820); 1842b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 4; 1852b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x0280c); 1862b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02824); 1872b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 4; 1882b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02810); 1892b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02828); 1902b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 4; 1912b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02814); 1922b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x0282c); 1932b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 8; 1941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02818); 1951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02830); 1961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1972b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter); 1981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 1991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (v_filter_1 > -1) { 2012b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (v_filter_1 > 4) 2022b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong v_filter_1 = 4; 2032b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192); 2042b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong for (line = 0; line < 16; line++) { 2052b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02900); 2062b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 4; 2072b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02904); 2082b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 8; 2091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02908); 2101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 2112b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1); 2121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 2131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (v_filter_2 > -1) { 2152b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (v_filter_2 > 4) 2162b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong v_filter_2 = 4; 2172b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192); 2182b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong for (line = 0; line < 16; line++) { 2192b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x0290c); 2202b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 4; 2212b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(read_dec(i), 0x02910); 2222b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong i += 8; 2231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02914); 2241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 2252b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2); 2261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 2271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 2281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2292b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrongstatic void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f) 2301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 2312b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 2321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2834, reg_2838, reg_283c; 2331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2844, reg_2854, reg_285c; 2341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2864, reg_2874, reg_2890; 2351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2870, reg_2870_base, reg_2870_offset; 2361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int x_cutoff; 2371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int h_filter; 2381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 master_width; 2391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_WARN 2412b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n", 2422b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x); 2431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* How wide is the src image */ 2452b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong x_cutoff = f->src_w + f->src_x; 2461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Set the display width */ 2482b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2834 = f->dst_w; 2491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2838 = reg_2834; 2501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Set the display position */ 2522b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2890 = f->dst_x; 2531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Index into the image horizontally */ 2551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870 = 0; 2561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* 2870 is normally fudged to align video coords with osd coords. 2581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil If running full screen, it causes an unwanted left shift 2591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Remove the fudge if we almost fill the screen. 2601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Gradually adjust the offset to avoid the video 'snapping' 2611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil left/right if it gets dragged through this region. 2621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Only do this if osd is full width. */ 2632b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->vis_w == 720) { 2642b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680)) 2652b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870 = 10 - (f->tru_x - f->pan_x) / 4; 2662b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660)) 2672b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870 = (10 + (f->tru_x - f->pan_x) / 2); 2681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2692b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->dst_w >= f->src_w) 2701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870 = reg_2870 << 16 | reg_2870; 2711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 2721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1); 2731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 2741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2752b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->dst_w < f->src_w) 2761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870 = 0x000d000e - reg_2870; 2771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 2781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870 = 0x0012000e - reg_2870; 2791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* We're also using 2870 to shift the image left (src_x & negative dst_x) */ 2812b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19; 2821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2832b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->dst_w >= f->src_w) { 2841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil x_cutoff &= ~1; 2852b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_width = (f->src_w * 0x00200000) / (f->dst_w); 2862b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (master_width * f->dst_w != f->src_w * 0x00200000) 2872b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_width++; 2881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2834 = (reg_2834 << 16) | x_cutoff; 2891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2838 = (reg_2838 << 16) | x_cutoff; 2901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_283c = master_width >> 2; 2911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2844 = master_width >> 2; 2921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2854 = master_width; 2931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_285c = master_width >> 1; 2941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2864 = master_width >> 1; 2951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 2961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* We also need to factor in the scaling 2971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil (src_w - dst_w) / (src_w / 4) */ 2982b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->dst_w > f->src_w) 2992b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14); 3001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 3011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870_base = 0; 3021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base); 3041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2874 = 0; 3052b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else if (f->dst_w < f->src_w / 2) { 3062b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_width = (f->src_w * 0x00080000) / f->dst_w; 3072b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (master_width * f->dst_w != f->src_w * 0x00080000) 3082b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_width++; 3091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2834 = (reg_2834 << 16) | x_cutoff; 3101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2838 = (reg_2838 << 16) | x_cutoff; 3111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_283c = master_width >> 2; 3121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2844 = master_width >> 1; 3131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2854 = master_width; 3141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_285c = master_width >> 1; 3151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2864 = master_width >> 1; 3162b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset; 3172b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16; 3181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2874 = 0x00000012; 3192b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 3202b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_width = (f->src_w * 0x00100000) / f->dst_w; 3212b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (master_width * f->dst_w != f->src_w * 0x00100000) 3222b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_width++; 3231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2834 = (reg_2834 << 16) | x_cutoff; 3241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2838 = (reg_2838 << 16) | x_cutoff; 3251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_283c = master_width >> 2; 3261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2844 = master_width >> 1; 3271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2854 = master_width; 3281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_285c = master_width >> 1; 3291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2864 = master_width >> 1; 3302b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1; 3312b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16; 3321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2874 = 0x00000001; 3331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 3341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Select the horizontal filter */ 3362b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->src_w == f->dst_w) { 3371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* An exact size match uses filter 0 */ 3381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil h_filter = 0; 3392b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 3401a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Figure out which filter to use */ 3412b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong h_filter = ((f->src_w << 16) / f->dst_w) >> 15; 3421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil h_filter = (h_filter >> 1) + (h_filter & 1); 3431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only an exact size match can use filter 0 */ 3442b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong h_filter += !h_filter; 3451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 3461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2834, 0x02834); 3481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2838, 0x02838); 3492b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n", 3502b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2834, reg_2834, yi->reg_2838, reg_2838); 3511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_283c, 0x0283c); 3531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2844, 0x02844); 3541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3552b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n", 3562b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_283c, reg_283c, yi->reg_2844, reg_2844); 3571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0x00080514, 0x02840); 3591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0x00100514, 0x02848); 3602b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n", 3612b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514); 3621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2854, 0x02854); 3642b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n", 3652b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2854, reg_2854); 3661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_285c, 0x0285c); 3681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2864, 0x02864); 3692b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n", 3702b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_285c, reg_285c, yi->reg_2864, reg_2864); 3711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2874, 0x02874); 3732b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n", 3742b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2874, reg_2874); 3751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2870, 0x02870); 3772b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n", 3782b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2870, reg_2870); 3791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3802b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(reg_2890, 0x02890); 3812b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n", 3822b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2890, reg_2890); 3831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only update the filter if we really need to */ 3852b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (h_filter != yi->h_filter) { 3862b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ivtv_yuv_filter(itv, h_filter, -1, -1); 3872b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->h_filter = h_filter; 3881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 3891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 3901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 3912b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrongstatic void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f) 3921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 3932b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 3941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 master_height; 3951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2918, reg_291c, reg_2920, reg_2928; 3961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2930, reg_2934, reg_293c; 3971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2940, reg_2944, reg_294c; 3981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2950, reg_2954, reg_2958, reg_295c; 3991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2960, reg_2964, reg_2968, reg_296c; 4001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_289c; 4012b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong u32 src_major_y, src_minor_y; 4022b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong u32 src_major_uv, src_minor_uv; 4031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 reg_2964_base, reg_2968_base; 4041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int v_filter_1, v_filter_2; 4051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4062b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_WARN 4072b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n", 4082b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y); 4091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* What scaling mode is being used... */ 4112b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Scaling mode Y: %s\n", 4122b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong f->interlaced_y ? "Interlaced" : "Progressive"); 4131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4142b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Scaling mode UV: %s\n", 4152b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong f->interlaced_uv ? "Interlaced" : "Progressive"); 4161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* What is the source video being treated as... */ 4182b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_WARN("Source video: %s\n", 4192b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong f->interlaced ? "Interlaced" : "Progressive"); 4201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* We offset into the image using two different index methods, so split 4221a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil the y source coord into two parts. */ 4232b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->src_y < 8) { 4242b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_minor_uv = f->src_y; 4252b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_major_uv = 0; 4262b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 4272b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_minor_uv = 8; 4282b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_major_uv = f->src_y - 8; 4291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 4301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4312b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_minor_y = src_minor_uv; 4322b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_major_y = src_major_uv; 4331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4342b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->offset_y) 4352b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong src_minor_y += 16; 4361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4372b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_y) 4382b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y); 4391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 4402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1); 4411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4422b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_uv) 4432b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1); 4441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 4452b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv); 4461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4472b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14; 4482b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14; 4491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 4502b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) { 4512b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_height = (f->src_h * 0x00400000) / f->dst_h; 4522b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2) 4532b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_height++; 4541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2920 = master_height >> 2; 4551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2928 = master_height >> 3; 4561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2930 = master_height; 4571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2940 = master_height >> 1; 4581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964_base >>= 3; 4591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968_base >>= 3; 4601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_296c = 0x00000000; 4612b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else if (f->dst_h >= f->src_h) { 4622b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_height = (f->src_h * 0x00400000) / f->dst_h; 4631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil master_height = (master_height >> 1) + (master_height & 1); 4641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2920 = master_height >> 2; 4651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2928 = master_height >> 2; 4661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2930 = master_height; 4671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2940 = master_height >> 1; 4681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_296c = 0x00000000; 4692b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_y) { 4701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964_base >>= 3; 4712b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 4722b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_296c++; 4731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964_base >>= 2; 4741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 4752b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_uv) 4762b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2928 >>= 1; 4771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968_base >>= 3; 4782b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else if (f->dst_h >= f->src_h / 2) { 4792b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_height = (f->src_h * 0x00200000) / f->dst_h; 4801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil master_height = (master_height >> 1) + (master_height & 1); 4811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2920 = master_height >> 2; 4821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2928 = master_height >> 2; 4831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2930 = master_height; 4841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2940 = master_height; 4851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_296c = 0x00000101; 4862b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_y) { 4871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964_base >>= 2; 4882b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 4892b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_296c++; 4901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964_base >>= 1; 4911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 4922b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_uv) 4932b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2928 >>= 1; 4941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968_base >>= 2; 4952b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 4962b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong master_height = (f->src_h * 0x00100000) / f->dst_h; 4971a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil master_height = (master_height >> 1) + (master_height & 1); 4981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2920 = master_height >> 2; 4991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2928 = master_height >> 2; 5001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2930 = master_height; 5011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2940 = master_height; 5021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964_base >>= 1; 5031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968_base >>= 2; 5041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_296c = 0x00000102; 5051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 5061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* FIXME These registers change depending on scaled / unscaled output 5081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil We really need to work out what they should be */ 5092b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->src_h == f->dst_h) { 5101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2934 = 0x00020000; 5111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_293c = 0x00100000; 5121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2944 = 0x00040000; 5131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_294c = 0x000b0000; 5142b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 5151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2934 = 0x00000FF0; 5161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_293c = 0x00000FF0; 5171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2944 = 0x00000FF0; 5181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_294c = 0x00000FF0; 5191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 5201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* The first line to be displayed */ 5222b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2950 = 0x00010000 + src_major_y; 5232b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_y) 5242b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2950 += 0x00010000; 5251a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2954 = reg_2950 + 1; 5261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5272b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2958 = 0x00010000 + (src_major_y >> 1); 5282b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->interlaced_uv) 5292b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2958 += 0x00010000; 5301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_295c = reg_2958 + 1; 5311a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5322b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (yi->decode_height == 480) 5331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_289c = 0x011e0017; 5341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 5351a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_289c = 0x01500017; 5361a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5372b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->dst_y < 0) 5382b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1); 5391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 5402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1); 5411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* How much of the source to decode. 5431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Take into account the source offset */ 5442b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) | 5452b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15); 5461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Calculate correct value for register 2964 */ 5482b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->src_h == f->dst_h) { 5491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964 = 1; 5502b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 5512b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2964 = 2 + ((f->dst_h << 1) / f->src_h); 5521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1); 5531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 5541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1); 5551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94); 5561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Okay, we've wasted time working out the correct value, 5581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil but if we use it, it fouls the the window alignment. 5591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Fudge it to what we want... */ 5601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16)); 5611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16)); 5621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Deviate further from what it should be. I find the flicker headache 5641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil inducing so try to reduce it slightly. Leave 2968 as-is otherwise 5651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil colours foul. */ 5662b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h)) 5672b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2); 5681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5692b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (!f->interlaced_y) 5702b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2964 -= 0x00010001; 5712b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (!f->interlaced_uv) 5722b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong reg_2968 -= 0x00010001; 5731a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2964 += ((reg_2964_base << 16) | reg_2964_base); 5751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil reg_2968 += ((reg_2968_base << 16) | reg_2968_base); 5761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Select the vertical filter */ 5782b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (f->src_h == f->dst_h) { 5791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* An exact size match uses filter 0/1 */ 5801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_1 = 0; 5811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_2 = 1; 5822b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 5831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Figure out which filter to use */ 5842b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15; 5851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1); 5861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only an exact size match can use filter 0 */ 5872b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong v_filter_1 += !v_filter_1; 5881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_2 = v_filter_1; 5891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 5901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 5911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2934, 0x02934); 5921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_293c, 0x0293c); 5932b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n", 5942b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2934, reg_2934, yi->reg_293c, reg_293c); 5951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2944, 0x02944); 5961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_294c, 0x0294c); 5972b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n", 5982b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2944, reg_2944, yi->reg_294c, reg_294c); 5991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Ensure 2970 is 0 (does it ever change ?) */ 6011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* write_reg(0,0x02970); */ 6022b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong/* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */ 6031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2930, 0x02938); 6051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2930, 0x02930); 6062b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n", 6072b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2930, reg_2930, yi->reg_2938, reg_2930); 6081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2928, 0x02928); 6102b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(reg_2928 + 0x514, 0x0292C); 6112b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n", 6122b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514); 6131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2920, 0x02920); 6152b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(reg_2920 + 0x514, 0x02924); 6162b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n", 6172b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514); 6181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6192b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(reg_2918, 0x02918); 6202b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(reg_291c, 0x0291C); 6212b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n", 6222b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2918, reg_2918, yi->reg_291c, reg_291c); 6231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_296c, 0x0296c); 6252b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n", 6262b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_296c, reg_296c); 6271a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6281a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2940, 0x02948); 6291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2940, 0x02940); 6302b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n", 6312b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2940, reg_2940, yi->reg_2948, reg_2940); 6321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6331a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2950, 0x02950); 6341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2954, 0x02954); 6352b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n", 6362b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2950, reg_2950, yi->reg_2954, reg_2954); 6371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2958, 0x02958); 6391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_295c, 0x0295C); 6402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n", 6412b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2958, reg_2958, yi->reg_295c, reg_295c); 6421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2960, 0x02960); 6442b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n", 6452b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2960, reg_2960); 6461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2964, 0x02964); 6481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(reg_2968, 0x02968); 6492b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n", 6502b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_2964, reg_2964, yi->reg_2968, reg_2968); 6511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6522b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(reg_289c, 0x0289c); 6532b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n", 6542b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->reg_289c, reg_289c); 6551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only update filter 1 if we really need to */ 6572b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (v_filter_1 != yi->v_filter_1) { 6582b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ivtv_yuv_filter(itv, -1, v_filter_1, -1); 6592b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->v_filter_1 = v_filter_1; 6601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 6611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only update filter 2 if we really need to */ 6632b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (v_filter_2 != yi->v_filter_2) { 6642b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ivtv_yuv_filter(itv, -1, -1, v_filter_2); 6652b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->v_filter_2 = v_filter_2; 6661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 6671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 6681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* Modify the supplied coordinate information to fit the visible osd area */ 6703b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrongstatic u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f) 6711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 6723b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_frame_info *of = &itv->yuv_info.old_frame_info; 6733b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong int osd_crop; 6741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 osd_scale; 6751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 yuv_update = 0; 6761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Sorry, but no negative coords for src */ 6783b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (f->src_x < 0) 6793b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_x = 0; 6803b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (f->src_y < 0) 6813b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_y = 0; 6821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Can only reduce width down to 1/4 original size */ 6843b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) { 6853b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_x += osd_crop / 2; 6863b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_w = (f->src_w - osd_crop) & ~3; 6873b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w = f->src_w / 4; 6883b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w += f->dst_w & 1; 6891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 6901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 6911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Can only reduce height down to 1/4 original size */ 6923b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (f->src_h / f->dst_h >= 2) { 6933b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong /* Overflow may be because we're running progressive, 6943b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong so force mode switch */ 6953b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->interlaced_y = 1; 6961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Make sure we're still within limits for interlace */ 6973b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) { 6981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* If we reach here we'll have to force the height. */ 6993b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_y += osd_crop / 2; 7003b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_h = (f->src_h - osd_crop) & ~3; 7013b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h = f->src_h / 4; 7023b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h += f->dst_h & 1; 7031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* If there's nothing to safe to display, we may as well stop now */ 7073b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 || 7082b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (int)f->src_w <= 2 || (int)f->src_h <= 2) { 7090bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong return IVTV_YUV_UPDATE_INVALID; 7101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Ensure video remains inside OSD area */ 7133b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong osd_scale = (f->src_h << 16) / f->dst_h; 7141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7153b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((osd_crop = f->pan_y - f->dst_y) > 0) { 7161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Falls off the upper edge - crop */ 7173b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_y += (osd_scale * osd_crop) >> 16; 7183b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_h -= (osd_scale * osd_crop) >> 16; 7193b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h -= osd_crop; 7203b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_y = 0; 7213b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong } else { 7223b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_y -= f->pan_y; 7231a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7253b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) { 7261a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Falls off the lower edge - crop */ 7273b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h -= osd_crop; 7283b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_h -= (osd_scale * osd_crop) >> 16; 7291a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7301a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7313b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong osd_scale = (f->src_w << 16) / f->dst_w; 7321a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7333b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((osd_crop = f->pan_x - f->dst_x) > 0) { 7341a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Fall off the left edge - crop */ 7353b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_x += (osd_scale * osd_crop) >> 16; 7363b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_w -= (osd_scale * osd_crop) >> 16; 7373b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w -= osd_crop; 7383b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_x = 0; 7393b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong } else { 7403b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_x -= f->pan_x; 7411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7433b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) { 7441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Falls off the right edge - crop */ 7453b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w -= osd_crop; 7463b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_w -= (osd_scale * osd_crop) >> 16; 7471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 74988ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong if (itv->yuv_info.track_osd) { 75088ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong /* The OSD can be moved. Track to it */ 75188ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f->dst_x += itv->yuv_info.osd_x_offset; 75288ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f->dst_y += itv->yuv_info.osd_y_offset; 75388ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong } 7541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Width & height for both src & dst must be even. 7561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Same for coordinates. */ 7573b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w &= ~1; 7583b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_x &= ~1; 7591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7603b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_w += f->src_x & 1; 7613b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_x &= ~1; 7621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7633b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_w &= ~1; 7643b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w &= ~1; 7651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7663b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h &= ~1; 7673b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_y &= ~1; 7681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7693b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_h += f->src_y & 1; 7703b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_y &= ~1; 7711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7723b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_h &= ~1; 7733b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h &= ~1; 7741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7753b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong /* Due to rounding, we may have reduced the output size to <1/4 of 7763b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong the source. Check again, but this time just resize. Don't change 7773b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong source coordinates */ 7783b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (f->dst_w < f->src_w / 4) { 7793b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_w &= ~3; 7803b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w = f->src_w / 4; 7813b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_w += f->dst_w & 1; 7821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7833b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (f->dst_h < f->src_h / 4) { 7843b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->src_h &= ~3; 7853b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h = f->src_h / 4; 7863b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f->dst_h += f->dst_h & 1; 7871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Check again. If there's nothing to safe to display, stop now */ 7903b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 || 7912b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (int)f->src_w <= 2 || (int)f->src_h <= 2) { 7920bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong return IVTV_YUV_UPDATE_INVALID; 7931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 7941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 7951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Both x offset & width are linked, so they have to be done together */ 7963b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) || 7972b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->dst_x != f->dst_x) || (of->src_x != f->src_x) || 7982b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) { 7991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL; 8001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 8011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8023b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) || 8032b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->dst_y != f->dst_y) || (of->src_y != f->src_y) || 8042b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) || 8052b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->lace_mode != f->lace_mode) || 8062b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->interlaced_y != f->interlaced_y) || 8072b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (of->interlaced_uv != f->interlaced_uv)) { 8081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil yuv_update |= IVTV_YUV_UPDATE_VERTICAL; 8091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 8101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return yuv_update; 8121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 8131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil/* Update the scaling register to the requested value */ 8152b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrongvoid ivtv_yuv_work_handler(struct ivtv *itv) 8161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 8173b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 8183b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_frame_info f; 8193b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong int frame = yi->update_frame; 8201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil u32 yuv_update; 8211a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8222b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame); 8233b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong f = yi->new_frame_info[frame]; 8241a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 82588ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong if (yi->track_osd) { 82688ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong /* Snapshot the osd pan info */ 82788ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.pan_x = yi->osd_x_pan; 82888ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.pan_y = yi->osd_y_pan; 82988ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.vis_w = yi->osd_vis_w; 83088ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.vis_h = yi->osd_vis_h; 83188ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong } else { 83288ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong /* Not tracking the osd, so assume full screen */ 83388ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.pan_x = 0; 83488ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.pan_y = 0; 83588ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.vis_w = 720; 83688ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong f.vis_h = yi->decode_height; 83788ab075aee974f70b7b0273a964810698c8a5b95Ian Armstrong } 8381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8391a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Calculate the display window coordinates. Exit if nothing left */ 8402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (!(yuv_update = ivtv_yuv_window_setup(itv, &f))) 8411a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return; 8421a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8430bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong if (yuv_update & IVTV_YUV_UPDATE_INVALID) { 8440bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong write_reg(0x01008080, 0x2898); 8450bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong } else if (yuv_update) { 8460bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong write_reg(0x00108080, 0x2898); 8471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8480bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL) 8493b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong ivtv_yuv_handle_horizontal(itv, &f); 8500bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong 8510bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong if (yuv_update & IVTV_YUV_UPDATE_VERTICAL) 8523b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong ivtv_yuv_handle_vertical(itv, &f); 8530bfeb04a9f3ad9ad8c9bbba062231ff1a76e4465Ian Armstrong } 8543b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong yi->old_frame_info = f; 8551a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 8561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8572b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrongstatic void ivtv_yuv_init(struct ivtv *itv) 8581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 859195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 860195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong 8611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil IVTV_DEBUG_YUV("ivtv_yuv_init\n"); 8621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 8631a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Take a snapshot of the current register settings */ 864195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2834 = read_reg(0x02834); 865195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2838 = read_reg(0x02838); 866195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_283c = read_reg(0x0283c); 867195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2840 = read_reg(0x02840); 868195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2844 = read_reg(0x02844); 869195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2848 = read_reg(0x02848); 870195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2854 = read_reg(0x02854); 871195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_285c = read_reg(0x0285c); 872195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2864 = read_reg(0x02864); 873195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2870 = read_reg(0x02870); 874195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2874 = read_reg(0x02874); 875195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2898 = read_reg(0x02898); 876195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2890 = read_reg(0x02890); 877195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong 878195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_289c = read_reg(0x0289c); 879195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2918 = read_reg(0x02918); 880195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_291c = read_reg(0x0291c); 881195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2920 = read_reg(0x02920); 882195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2924 = read_reg(0x02924); 883195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2928 = read_reg(0x02928); 884195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_292c = read_reg(0x0292c); 885195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2930 = read_reg(0x02930); 886195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2934 = read_reg(0x02934); 887195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2938 = read_reg(0x02938); 888195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_293c = read_reg(0x0293c); 889195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2940 = read_reg(0x02940); 890195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2944 = read_reg(0x02944); 891195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2948 = read_reg(0x02948); 892195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_294c = read_reg(0x0294c); 893195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2950 = read_reg(0x02950); 894195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2954 = read_reg(0x02954); 895195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2958 = read_reg(0x02958); 896195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_295c = read_reg(0x0295c); 897195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2960 = read_reg(0x02960); 898195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2964 = read_reg(0x02964); 899195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2968 = read_reg(0x02968); 900195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_296c = read_reg(0x0296c); 901195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->reg_2970 = read_reg(0x02970); 902195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong 903195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->v_filter_1 = -1; 904195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->v_filter_2 = -1; 905195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->h_filter = -1; 9061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 9071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Set some valid size info */ 908195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF; 909195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF; 9101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 9111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Bit 2 of reg 2878 indicates current decoder output format 9121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 0 : NTSC 1 : PAL */ 9131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (read_reg(0x2878) & 4) 914195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->decode_height = 576; 9151a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil else 916195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->decode_height = 480; 917b4b38bd63c07c8927b43c6c378eca1db10fdaf2eIan Armstrong 918195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong if (!itv->osd_info) { 919195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->osd_vis_w = 720 - yi->osd_x_offset; 920195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; 921b4b38bd63c07c8927b43c6c378eca1db10fdaf2eIan Armstrong } else { 922195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong /* If no visible size set, assume full size */ 923195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong if (!yi->osd_vis_w) 924195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->osd_vis_w = 720 - yi->osd_x_offset; 925195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong 9262b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (!yi->osd_vis_h) { 927195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; 9282b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) { 929195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong /* If output video standard has changed, requested height may 9302b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong not be legal */ 9312b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n", 9322b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->osd_vis_h + yi->osd_y_offset, 9332b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->decode_height); 9342b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; 935b4b38bd63c07c8927b43c6c378eca1db10fdaf2eIan Armstrong } 936b4b38bd63c07c8927b43c6c378eca1db10fdaf2eIan Armstrong } 9371a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 9381a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ 9393f98387efa9333c5765d36e144c47c107d6ba64aHans Verkuil yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); 9402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (yi->blanking_ptr) { 9418ac05ae3192ce8a71fc84e4a88772cce0c09173cHans Verkuil yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); 9422b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 943195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong yi->blanking_dmaptr = 0; 944195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n"); 9451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 9461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 9471a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Enable YUV decoder output */ 9481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg_sync(0x01, IVTV_REG_VDM); 9491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 9501a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); 951195b1252517d504391d29f71b789d4c1c9f605e0Ian Armstrong atomic_set(&yi->next_dma_frame, 0); 9521a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 9531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 954a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong/* Get next available yuv buffer on PVR350 */ 9555eedc466758b5743512d38b5d1eab6f799a39e00Adrian Bunkstatic void ivtv_yuv_next_free(struct ivtv *itv) 9561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 957a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong int draw, display; 958a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 9591a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 960a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong if (atomic_read(&yi->next_dma_frame) == -1) 961a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong ivtv_yuv_init(itv); 9621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 963a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong draw = atomic_read(&yi->next_fill_frame); 964a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong display = atomic_read(&yi->next_dma_frame); 9651a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 966a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong if (display > draw) 967a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong display -= IVTV_YUV_BUFFERS; 9681a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 969a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong if (draw - display >= yi->max_frames_buffered) 970a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS; 971a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong else 972a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong yi->new_frame_info[draw].update = 0; 973a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 974a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong yi->draw_frame = draw; 975a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong} 976a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 977a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong/* Set up frame according to ivtv_dma_frame parameters */ 9785eedc466758b5743512d38b5d1eab6f799a39e00Adrian Bunkstatic void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) 979a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong{ 980a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 981a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong u8 frame = yi->draw_frame; 9823b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS; 9833b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_frame_info *nf = &yi->new_frame_info[frame]; 9843b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong struct yuv_frame_info *of = &yi->new_frame_info[last_frame]; 9853b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong int lace_threshold = yi->lace_threshold; 986a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 987a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong /* Preserve old update flag in case we're overwriting a queued frame */ 9883b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong int update = nf->update; 9891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 9901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Take a snapshot of the yuv coordinate information */ 9913b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->src_x = args->src.left; 9923b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->src_y = args->src.top; 9933b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->src_w = args->src.width; 9943b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->src_h = args->src.height; 9953b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->dst_x = args->dst.left; 9963b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->dst_y = args->dst.top; 9973b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->dst_w = args->dst.width; 9983b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->dst_h = args->dst.height; 9993b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->tru_x = args->dst.left; 10003b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->tru_w = args->src_width; 10013b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->tru_h = args->src_height; 1002bfd7beacff2b5c811badb587a74c3dfbf7f98721Ian Armstrong 10031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Are we going to offset the Y plane */ 10043b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0; 10051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 10063b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->update = 0; 10073b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 0; 10083b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 0; 10093b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->delay = 0; 10103b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->sync_field = 0; 10113b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK; 10123b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong 10133b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (lace_threshold < 0) 10143b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong lace_threshold = yi->decode_height - 1; 10153b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong 10163b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong /* Work out the lace settings */ 10173b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong switch (nf->lace_mode) { 10183b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */ 10193b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced = 0; 10203b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021)) 10213b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 0; 10223b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong else 10233b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 1; 10243b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong 10253b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2)) 10263b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 0; 10273b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong else 10283b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 1; 10293b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong break; 10303b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong 10313b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong case IVTV_YUV_MODE_AUTO: 10323b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) { 10333b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced = 0; 10343b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if ((nf->tru_h < 512) || 10352b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (nf->tru_h > 576 && nf->tru_h < 1021) || 10362b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong (nf->tru_w > 720 && nf->tru_h < 1021)) 10373b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 0; 10383b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong else 10393b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 1; 10403b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2)) 10413b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 0; 10423b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong else 10433b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 1; 10443b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong } else { 10453b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced = 1; 10463b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 1; 10473b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 1; 10483b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong } 10493b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong break; 10503b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong 10513b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */ 10523b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong default: 10533b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced = 1; 10543b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_y = 1; 10553b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->interlaced_uv = 1; 10563b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong break; 10571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 10581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 10593b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) { 10603b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong yi->old_frame_info_args = *nf; 10613b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->update = 1; 10622b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame); 10633b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong } 1064943e8910db31e36d945f2bf7d4c273ca5fa01f6eIan Armstrong 10653b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->update |= update; 10663b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->sync_field = yi->lace_sync_field; 10673b5c1c8e71eb8fe2297a5884db59108e3c8b44c5Ian Armstrong nf->delay = nf->sync_field != of->sync_field; 1068a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong} 1069a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 1070a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong/* Frame is complete & ready for display */ 1071a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrongvoid ivtv_yuv_frame_complete(struct ivtv *itv) 1072a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong{ 1073a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong atomic_set(&itv->yuv_info.next_fill_frame, 1074a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); 1075a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong} 1076a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong 10775eedc466758b5743512d38b5d1eab6f799a39e00Adrian Bunkstatic int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) 1078a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong{ 1079a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong DEFINE_WAIT(wait); 1080a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong int rc = 0; 1081a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong int got_sig = 0; 10821a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* DMA the frame */ 10831a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil mutex_lock(&itv->udma.lock); 10841a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 10851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) { 10861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil mutex_unlock(&itv->udma.lock); 10871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return rc; 10881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 10891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 10901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil ivtv_udma_prepare(itv); 10911a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); 10921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* if no UDMA is pending and no UDMA is in progress, then the DMA 10932b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong is finished */ 1094ec105a42ac397366e05888ea96503ab3b57f79adHans Verkuil while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || 1095ec105a42ac397366e05888ea96503ab3b57f79adHans Verkuil test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { 10961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* don't interrupt if the DMA is in progress but break off 10972b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong a still pending DMA. */ 10981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil got_sig = signal_pending(current); 10991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) 11001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil break; 11011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil got_sig = 0; 11021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil schedule(); 11031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 11041a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil finish_wait(&itv->dma_waitq, &wait); 11051a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 11061a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Unmap Last DMA Xfer */ 11071a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil ivtv_udma_unmap(itv); 11081a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 11091a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil if (got_sig) { 11101a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil IVTV_DEBUG_INFO("User stopped YUV UDMA\n"); 11111a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil mutex_unlock(&itv->udma.lock); 11121a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return -EINTR; 11131a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 11141a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 1115a3e5f5e2dfb50bebca24329e5377d804c6e3eb1bIan Armstrong ivtv_yuv_frame_complete(itv); 11161a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 11171a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil mutex_unlock(&itv->udma.lock); 11181a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil return rc; 11191a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 11201a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 112177aded6ba51f01335840ce8e18b413067810b68eIan Armstrong/* Setup frame according to V4L2 parameters */ 112277aded6ba51f01335840ce8e18b413067810b68eIan Armstrongvoid ivtv_yuv_setup_stream_frame(struct ivtv *itv) 112377aded6ba51f01335840ce8e18b413067810b68eIan Armstrong{ 112477aded6ba51f01335840ce8e18b413067810b68eIan Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 112577aded6ba51f01335840ce8e18b413067810b68eIan Armstrong struct ivtv_dma_frame dma_args; 112677aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 112777aded6ba51f01335840ce8e18b413067810b68eIan Armstrong ivtv_yuv_next_free(itv); 112877aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 112977aded6ba51f01335840ce8e18b413067810b68eIan Armstrong /* Copy V4L2 parameters to an ivtv_dma_frame struct... */ 1130a6a3a17b7fdaf824e6d73e8e4a94c9d149302f74Harvey Harrison dma_args.y_source = NULL; 1131a6a3a17b7fdaf824e6d73e8e4a94c9d149302f74Harvey Harrison dma_args.uv_source = NULL; 113277aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.src.left = 0; 113377aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.src.top = 0; 113477aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.src.width = yi->v4l2_src_w; 113577aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.src.height = yi->v4l2_src_h; 113677aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.dst = yi->main_rect; 113777aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.src_width = yi->v4l2_src_w; 113877aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.src_height = yi->v4l2_src_h; 113977aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 114077aded6ba51f01335840ce8e18b413067810b68eIan Armstrong /* ... and use the same setup routine as ivtv_yuv_prep_frame */ 114177aded6ba51f01335840ce8e18b413067810b68eIan Armstrong ivtv_yuv_setup_frame(itv, &dma_args); 114277aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 114377aded6ba51f01335840ce8e18b413067810b68eIan Armstrong if (!itv->dma_data_req_offset) 114477aded6ba51f01335840ce8e18b413067810b68eIan Armstrong itv->dma_data_req_offset = yuv_offset[yi->draw_frame]; 114577aded6ba51f01335840ce8e18b413067810b68eIan Armstrong} 114677aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 114777aded6ba51f01335840ce8e18b413067810b68eIan Armstrong/* Attempt to dma a frame from a user buffer */ 1148b0510f8dc73dce56f35337487c6374ae84b15446Al Viroint ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) 114977aded6ba51f01335840ce8e18b413067810b68eIan Armstrong{ 115077aded6ba51f01335840ce8e18b413067810b68eIan Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 115177aded6ba51f01335840ce8e18b413067810b68eIan Armstrong struct ivtv_dma_frame dma_args; 1152cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil int res; 115377aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 115477aded6ba51f01335840ce8e18b413067810b68eIan Armstrong ivtv_yuv_setup_stream_frame(itv); 115577aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 115677aded6ba51f01335840ce8e18b413067810b68eIan Armstrong /* We only need to supply source addresses for this */ 115777aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.y_source = src; 115877aded6ba51f01335840ce8e18b413067810b68eIan Armstrong dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); 1159cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil /* Wait for frame DMA. Note that serialize_lock is locked, 1160cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil so to allow other processes to access the driver while 1161cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil we are waiting unlock first and later lock again. */ 1162cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil mutex_unlock(&itv->serialize_lock); 1163cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil res = ivtv_yuv_udma_frame(itv, &dma_args); 1164cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil mutex_lock(&itv->serialize_lock); 1165cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil return res; 116677aded6ba51f01335840ce8e18b413067810b68eIan Armstrong} 116777aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 116877aded6ba51f01335840ce8e18b413067810b68eIan Armstrong/* IVTV_IOC_DMA_FRAME ioctl handler */ 116977aded6ba51f01335840ce8e18b413067810b68eIan Armstrongint ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) 117077aded6ba51f01335840ce8e18b413067810b68eIan Armstrong{ 1171cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil int res; 117277aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 1173cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ 117477aded6ba51f01335840ce8e18b413067810b68eIan Armstrong ivtv_yuv_next_free(itv); 117577aded6ba51f01335840ce8e18b413067810b68eIan Armstrong ivtv_yuv_setup_frame(itv, args); 1176cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil /* Wait for frame DMA. Note that serialize_lock is locked, 1177cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil so to allow other processes to access the driver while 1178cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil we are waiting unlock first and later lock again. */ 1179cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil mutex_unlock(&itv->serialize_lock); 1180cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil res = ivtv_yuv_udma_frame(itv, args); 1181cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil mutex_lock(&itv->serialize_lock); 1182cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil return res; 118377aded6ba51f01335840ce8e18b413067810b68eIan Armstrong} 118477aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 11851a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuilvoid ivtv_yuv_close(struct ivtv *itv) 11861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil{ 11872b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong struct yuv_playback_info *yi = &itv->yuv_info; 11881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil int h_filter, v_filter_1, v_filter_2; 11891a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 11901a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil IVTV_DEBUG_YUV("ivtv_yuv_close\n"); 1191cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil mutex_unlock(&itv->serialize_lock); 11921a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil ivtv_waitq(&itv->vsync_waitq); 1193cdc037817cc15caf931cd3476970860d62f1985cHans Verkuil mutex_lock(&itv->serialize_lock); 11941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 11952bd7ac55c31cb4f42e331d69dde9fc034a68944fIan Armstrong yi->running = 0; 11962b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong atomic_set(&yi->next_dma_frame, -1); 11972b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong atomic_set(&yi->next_fill_frame, 0); 11981a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 11991a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Reset registers we have changed so mpeg playback works */ 12001a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12011a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* If we fully restore this register, the display may remain active. 12021a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil Restore, but set one bit to blank the video. Firmware will always 12031a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil clear this bit when needed, so not a problem. */ 12042b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2898 | 0x01000000, 0x2898); 12052b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong 12062b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2834, 0x02834); 12072b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2838, 0x02838); 12082b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_283c, 0x0283c); 12092b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2840, 0x02840); 12102b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2844, 0x02844); 12112b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2848, 0x02848); 12122b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2854, 0x02854); 12132b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_285c, 0x0285c); 12142b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2864, 0x02864); 12152b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2870, 0x02870); 12162b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2874, 0x02874); 12172b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2890, 0x02890); 12182b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_289c, 0x0289c); 12192b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong 12202b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2918, 0x02918); 12212b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_291c, 0x0291c); 12222b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2920, 0x02920); 12232b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2924, 0x02924); 12242b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2928, 0x02928); 12252b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_292c, 0x0292c); 12262b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2930, 0x02930); 12272b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2934, 0x02934); 12282b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2938, 0x02938); 12292b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_293c, 0x0293c); 12302b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2940, 0x02940); 12312b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2944, 0x02944); 12322b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2948, 0x02948); 12332b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_294c, 0x0294c); 12342b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2950, 0x02950); 12352b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2954, 0x02954); 12362b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2958, 0x02958); 12372b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_295c, 0x0295c); 12382b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2960, 0x02960); 12392b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2964, 0x02964); 12402b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2968, 0x02968); 12412b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_296c, 0x0296c); 12422b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong write_reg(yi->reg_2970, 0x02970); 12431a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12441a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Prepare to restore filters */ 12451a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12461a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* First the horizontal filter */ 12472b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) { 12481a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* An exact size match uses filter 0 */ 12491a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil h_filter = 0; 12502b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 12511a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Figure out which filter to use */ 12522b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15; 12531a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil h_filter = (h_filter >> 1) + (h_filter & 1); 12541a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only an exact size match can use filter 0. */ 12552b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong h_filter += !h_filter; 12561a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 12571a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12581a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Now the vertical filter */ 12592b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) { 12601a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* An exact size match uses filter 0/1 */ 12611a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_1 = 0; 12621a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_2 = 1; 12632b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong } else { 12641a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Figure out which filter to use */ 12652b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15; 12661a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1); 12671a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Only an exact size match can use filter 0 */ 12682b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong v_filter_1 += !v_filter_1; 12691a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil v_filter_2 = v_filter_1; 12701a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 12711a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12721a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Now restore the filters */ 12732b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2); 12741a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12751a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* and clear a few registers */ 12761a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02814); 12771a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x0282c); 12781a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02904); 12791a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil write_reg(0, 0x02910); 12801a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12811a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Release the blanking buffer */ 12822b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong if (yi->blanking_ptr) { 12832b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong kfree(yi->blanking_ptr); 12842b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->blanking_ptr = NULL; 12858ac05ae3192ce8a71fc84e4a88772cce0c09173cHans Verkuil pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); 12861a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil } 12871a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12881a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* Invalidate the old dimension information */ 12892b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->old_frame_info.src_w = 0; 12902b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->old_frame_info.src_h = 0; 12912b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->old_frame_info_args.src_w = 0; 12922b057e8dc6cc8318956fef92b77a4e86985e84d9Ian Armstrong yi->old_frame_info_args.src_h = 0; 12931a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil 12941a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil /* All done. */ 12951a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); 12961a0adaf37c30e89e44d1470ef604a930999a5826Hans Verkuil} 1297