@@ -304,11 +304,6 @@ struct ipu_task_entry {
304304 atomic_t res_get ;
305305
306306 struct ipu_task_entry * parent ;
307- char * vditmpbuf [2 ];
308- u32 old_save_lines ;
309- u32 old_size ;
310- bool buf1filled ;
311- bool buf0filled ;
312307
313308 vdoa_handle_t vdoa_handle ;
314309 struct vdoa_output_mem {
@@ -1721,7 +1716,7 @@ static int queue_split_task(struct ipu_task_entry *t,
17211716{
17221717 int err [4 ];
17231718 int ret = 0 ;
1724- int i , j ;
1719+ int i , j , invert ;
17251720 struct ipu_task_entry * tsk = NULL ;
17261721 struct mutex * lock = & t -> split_lock ;
17271722 struct mutex * vdic_lock = & t -> vdic_lock ;
@@ -1738,6 +1733,11 @@ static int queue_split_task(struct ipu_task_entry *t,
17381733 sp_task [j ].task_no = t -> task_no ;
17391734 }
17401735
1736+ /* Note: When deinterlace is active, insert UP_STRIPE before DOWN_STRIPE.
1737+ * This will avoid the "tearing line" problem formerly addressed by ENGR00161315
1738+ */
1739+ invert = (t -> input .deinterlace .enable ) ? (UP_STRIPE | DOWN_STRIPE ) : 0 ;
1740+
17411741 if (t -> set .split_mode == RL_SPLIT ) {
17421742 i = 0 ;
17431743 err [i ] = create_split_task (RIGHT_STRIPE , & sp_task [i ]);
@@ -1747,26 +1747,26 @@ static int queue_split_task(struct ipu_task_entry *t,
17471747 err [i ] = create_split_task (LEFT_STRIPE , & sp_task [i ]);
17481748 } else if (t -> set .split_mode == UD_SPLIT ) {
17491749 i = 0 ;
1750- err [i ] = create_split_task (DOWN_STRIPE , & sp_task [i ]);
1750+ err [i ] = create_split_task (DOWN_STRIPE ^ invert , & sp_task [i ]);
17511751 if (err [i ] < 0 )
17521752 goto err_start ;
17531753 i = 1 ;
1754- err [i ] = create_split_task (UP_STRIPE , & sp_task [i ]);
1754+ err [i ] = create_split_task (UP_STRIPE ^ invert , & sp_task [i ]);
17551755 } else {
17561756 i = 0 ;
1757- err [i ] = create_split_task (RIGHT_STRIPE | DOWN_STRIPE , & sp_task [i ]);
1757+ err [i ] = create_split_task (( RIGHT_STRIPE | DOWN_STRIPE ) ^ invert , & sp_task [i ]);
17581758 if (err [i ] < 0 )
17591759 goto err_start ;
17601760 i = 1 ;
1761- err [i ] = create_split_task (LEFT_STRIPE | DOWN_STRIPE , & sp_task [i ]);
1761+ err [i ] = create_split_task (( LEFT_STRIPE | DOWN_STRIPE ) ^ invert , & sp_task [i ]);
17621762 if (err [i ] < 0 )
17631763 goto err_start ;
17641764 i = 2 ;
1765- err [i ] = create_split_task (RIGHT_STRIPE | UP_STRIPE , & sp_task [i ]);
1765+ err [i ] = create_split_task (( RIGHT_STRIPE | UP_STRIPE ) ^ invert , & sp_task [i ]);
17661766 if (err [i ] < 0 )
17671767 goto err_start ;
17681768 i = 3 ;
1769- err [i ] = create_split_task (LEFT_STRIPE | UP_STRIPE , & sp_task [i ]);
1769+ err [i ] = create_split_task (( LEFT_STRIPE | UP_STRIPE ) ^ invert , & sp_task [i ]);
17701770 }
17711771
17721772err_start :
@@ -2407,219 +2407,11 @@ static irqreturn_t task_irq_handler(int irq, void *dev_id)
24072407 return IRQ_HANDLED ;
24082408}
24092409
2410- /* Fix deinterlace up&down split mode medium line */
2411- static void vdi_split_process (struct ipu_soc * ipu , struct ipu_task_entry * t )
2412- {
2413- u32 vdi_size ;
2414- u32 vdi_save_lines ;
2415- u32 stripe_mode ;
2416- u32 task_no ;
2417- u32 i , offset_addr ;
2418- u32 line_size ;
2419- unsigned char * base_off ;
2420- struct ipu_task_entry * parent = t -> parent ;
2421- struct mutex * lock = & parent -> vdic_lock ;
2422-
2423- if (!parent ) {
2424- dev_err (t -> dev , "ERR[0x%x]invalid parent\n" , t -> task_no );
2425- return ;
2426- }
2427- mutex_lock (lock );
2428- stripe_mode = t -> task_no & 0xf ;
2429- task_no = t -> task_no >> 4 ;
2430-
2431- /* Save both luma and chroma part for interleaved YUV(e.g. YUYV).
2432- * Save luma part for non-interleaved and partial-interleaved
2433- * YUV format (e.g NV12 and YV12). */
2434- if (t -> output .format == IPU_PIX_FMT_YUYV ||
2435- t -> output .format == IPU_PIX_FMT_UYVY )
2436- line_size = t -> output .crop .w * fmt_to_bpp (t -> output .format )/8 ;
2437- else
2438- line_size = t -> output .crop .w ;
2439-
2440- vdi_save_lines = (t -> output .crop .h - t -> set .sp_setting .ud_split_line )/2 ;
2441- vdi_size = vdi_save_lines * line_size ;
2442- if (vdi_save_lines <= 0 ) {
2443- dev_err (t -> dev , "[0x%p] vdi_save_line error\n" , (void * )t );
2444- mutex_unlock (lock );
2445- return ;
2446- }
2447-
2448- /*check vditmpbuf buffer have alloced or buffer size is changed */
2449- if ((vdi_save_lines != parent -> old_save_lines ) ||
2450- (vdi_size != parent -> old_size )) {
2451- if (parent -> vditmpbuf [0 ] != NULL )
2452- kfree (parent -> vditmpbuf [0 ]);
2453- if (parent -> vditmpbuf [1 ] != NULL )
2454- kfree (parent -> vditmpbuf [1 ]);
2455-
2456- parent -> vditmpbuf [0 ] = kmalloc (vdi_size , GFP_KERNEL );
2457- if (parent -> vditmpbuf [0 ] == NULL ) {
2458- dev_err (t -> dev ,
2459- "[0x%p]Falied Alloc vditmpbuf[0]\n" , (void * )t );
2460- mutex_unlock (lock );
2461- return ;
2462- }
2463- memset (parent -> vditmpbuf [0 ], 0 , vdi_size );
2464-
2465- parent -> vditmpbuf [1 ] = kmalloc (vdi_size , GFP_KERNEL );
2466- if (parent -> vditmpbuf [1 ] == NULL ) {
2467- dev_err (t -> dev ,
2468- "[0x%p]Falied Alloc vditmpbuf[1]\n" , (void * )t );
2469- mutex_unlock (lock );
2470- return ;
2471- }
2472- memset (parent -> vditmpbuf [1 ], 0 , vdi_size );
2473-
2474- parent -> old_save_lines = vdi_save_lines ;
2475- parent -> old_size = vdi_size ;
2476- }
2477-
2478- if (pfn_valid (t -> output .paddr >> PAGE_SHIFT )) {
2479- base_off = page_address (pfn_to_page (t -> output .paddr >> PAGE_SHIFT ));
2480- base_off += t -> output .paddr & ((1 << PAGE_SHIFT ) - 1 );
2481- } else {
2482- base_off = (char * )ioremap_nocache (t -> output .paddr ,
2483- t -> output .width * t -> output .height *
2484- fmt_to_bpp (t -> output .format )/8 );
2485- }
2486- if (base_off == NULL ) {
2487- dev_err (t -> dev , "ERR[0x%p]Failed get virtual address\n" , t );
2488- mutex_unlock (lock );
2489- return ;
2490- }
2491-
2492- /* UP stripe or UP&LEFT stripe */
2493- if ((stripe_mode == UP_STRIPE ) ||
2494- (stripe_mode == (UP_STRIPE | LEFT_STRIPE ))) {
2495- if (!parent -> buf0filled ) {
2496- offset_addr = t -> set .o_off +
2497- t -> set .sp_setting .ud_split_line * t -> set .ostride ;
2498- dmac_flush_range (base_off + offset_addr ,
2499- base_off + offset_addr + vdi_size );
2500- outer_flush_range (t -> output .paddr + offset_addr ,
2501- t -> output .paddr + offset_addr + vdi_size );
2502-
2503- for (i = 0 ; i < vdi_save_lines ; i ++ )
2504- memcpy (parent -> vditmpbuf [0 ] + i * line_size ,
2505- base_off + offset_addr +
2506- i * t -> set .ostride , line_size );
2507- parent -> buf0filled = true;
2508- } else {
2509- offset_addr = t -> set .o_off + (t -> output .crop .h -
2510- vdi_save_lines ) * t -> set .ostride ;
2511- for (i = 0 ; i < vdi_save_lines ; i ++ )
2512- memcpy (base_off + offset_addr + i * t -> set .ostride ,
2513- parent -> vditmpbuf [0 ] + i * line_size , line_size );
2514-
2515- dmac_flush_range (base_off + offset_addr ,
2516- base_off + offset_addr + i * t -> set .ostride );
2517- outer_flush_range (t -> output .paddr + offset_addr ,
2518- t -> output .paddr + offset_addr + i * t -> set .ostride );
2519- parent -> buf0filled = false;
2520- }
2521- }
2522- /*Down stripe or Down&Left stripe*/
2523- else if ((stripe_mode == DOWN_STRIPE ) ||
2524- (stripe_mode == (DOWN_STRIPE | LEFT_STRIPE ))) {
2525- if (!parent -> buf0filled ) {
2526- offset_addr = t -> set .o_off + vdi_save_lines * t -> set .ostride ;
2527- dmac_flush_range (base_off + offset_addr ,
2528- base_off + offset_addr + vdi_size );
2529- outer_flush_range (t -> output .paddr + offset_addr ,
2530- t -> output .paddr + offset_addr + vdi_size );
2531-
2532- for (i = 0 ; i < vdi_save_lines ; i ++ )
2533- memcpy (parent -> vditmpbuf [0 ] + i * line_size ,
2534- base_off + offset_addr + i * t -> set .ostride ,
2535- line_size );
2536- parent -> buf0filled = true;
2537- } else {
2538- offset_addr = t -> set .o_off ;
2539- for (i = 0 ; i < vdi_save_lines ; i ++ )
2540- memcpy (base_off + offset_addr + i * t -> set .ostride ,
2541- parent -> vditmpbuf [0 ] + i * line_size ,
2542- line_size );
2543-
2544- dmac_flush_range (base_off + offset_addr ,
2545- base_off + offset_addr + i * t -> set .ostride );
2546- outer_flush_range (t -> output .paddr + offset_addr ,
2547- t -> output .paddr + offset_addr + i * t -> set .ostride );
2548- parent -> buf0filled = false;
2549- }
2550- }
2551- /*Up&Right stripe*/
2552- else if (stripe_mode == (UP_STRIPE | RIGHT_STRIPE )) {
2553- if (!parent -> buf1filled ) {
2554- offset_addr = t -> set .o_off +
2555- t -> set .sp_setting .ud_split_line * t -> set .ostride ;
2556- dmac_flush_range (base_off + offset_addr ,
2557- base_off + offset_addr + vdi_size );
2558- outer_flush_range (t -> output .paddr + offset_addr ,
2559- t -> output .paddr + offset_addr + vdi_size );
2560-
2561- for (i = 0 ; i < vdi_save_lines ; i ++ )
2562- memcpy (parent -> vditmpbuf [1 ] + i * line_size ,
2563- base_off + offset_addr + i * t -> set .ostride ,
2564- line_size );
2565- parent -> buf1filled = true;
2566- } else {
2567- offset_addr = t -> set .o_off +
2568- (t -> output .crop .h - vdi_save_lines )* t -> set .ostride ;
2569- for (i = 0 ; i < vdi_save_lines ; i ++ )
2570- memcpy (base_off + offset_addr + i * t -> set .ostride ,
2571- parent -> vditmpbuf [1 ] + i * line_size ,
2572- line_size );
2573-
2574- dmac_flush_range (base_off + offset_addr ,
2575- base_off + offset_addr + i * t -> set .ostride );
2576- outer_flush_range (t -> output .paddr + offset_addr ,
2577- t -> output .paddr + offset_addr + i * t -> set .ostride );
2578- parent -> buf1filled = false;
2579- }
2580- }
2581- /*Down stripe or Down&Right stript*/
2582- else if (stripe_mode == (DOWN_STRIPE | RIGHT_STRIPE )) {
2583- if (!parent -> buf1filled ) {
2584- offset_addr = t -> set .o_off + vdi_save_lines * t -> set .ostride ;
2585- dmac_flush_range (base_off + offset_addr ,
2586- base_off + offset_addr + vdi_save_lines * t -> set .ostride );
2587- outer_flush_range (t -> output .paddr + offset_addr ,
2588- t -> output .paddr + offset_addr + vdi_save_lines * t -> set .ostride );
2589-
2590- for (i = 0 ; i < vdi_save_lines ; i ++ )
2591- memcpy (parent -> vditmpbuf [1 ] + i * line_size ,
2592- base_off + offset_addr + i * t -> set .ostride ,
2593- line_size );
2594- parent -> buf1filled = true;
2595- } else {
2596- offset_addr = t -> set .o_off ;
2597- for (i = 0 ; i < vdi_save_lines ; i ++ )
2598- memcpy (base_off + offset_addr + i * t -> set .ostride ,
2599- parent -> vditmpbuf [1 ] + i * line_size ,
2600- line_size );
2601-
2602- dmac_flush_range (base_off + offset_addr ,
2603- base_off + offset_addr + vdi_save_lines * t -> set .ostride );
2604- outer_flush_range (t -> output .paddr + offset_addr ,
2605- t -> output .paddr + offset_addr + vdi_save_lines * t -> set .ostride );
2606- parent -> buf1filled = false;
2607- }
2608- }
2609- if (!pfn_valid (t -> output .paddr >> PAGE_SHIFT ))
2610- iounmap (base_off );
2611- mutex_unlock (lock );
2612- }
2613-
26142410static void do_task_release (struct ipu_task_entry * t , int fail )
26152411{
26162412 int ret ;
26172413 struct ipu_soc * ipu = t -> ipu ;
26182414
2619- if (t -> input .deinterlace .enable && !fail &&
2620- (t -> task_no & (UP_STRIPE | DOWN_STRIPE )))
2621- vdi_split_process (ipu , t );
2622-
26232415 ipu_free_irq (ipu , t -> irq , t );
26242416
26252417 if (t -> vdoa_dma .vaddr )
@@ -3180,9 +2972,6 @@ static void wait_split_task_complete(struct ipu_task_entry *parent,
31802972 kref_put (& tsk -> refcount , task_mem_free );
31812973 }
31822974
3183- kfree (parent -> vditmpbuf [0 ]);
3184- kfree (parent -> vditmpbuf [1 ]);
3185-
31862975 if (ret < 0 )
31872976 parent -> state = STATE_TIMEOUT ;
31882977 else
0 commit comments