18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/************************************************************************** 38c2ecf20Sopenharmony_ci * Copyright (c) 2007-2011, Intel Corporation. 48c2ecf20Sopenharmony_ci * All Rights Reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to 78c2ecf20Sopenharmony_ci * develop this driver. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci **************************************************************************/ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/console.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/errno.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/mm.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/slab.h> 198c2ecf20Sopenharmony_ci#include <linux/string.h> 208c2ecf20Sopenharmony_ci#include <linux/tty.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <drm/drm.h> 238c2ecf20Sopenharmony_ci#include <drm/drm_crtc.h> 248c2ecf20Sopenharmony_ci#include <drm/drm_fb_helper.h> 258c2ecf20Sopenharmony_ci#include <drm/drm_fourcc.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include "psb_drv.h" 288c2ecf20Sopenharmony_ci#include "psb_reg.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/** 318c2ecf20Sopenharmony_ci * psb_spank - reset the 2D engine 328c2ecf20Sopenharmony_ci * @dev_priv: our PSB DRM device 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Soft reset the graphics engine and then reload the necessary registers. 358c2ecf20Sopenharmony_ci * We use this at initialisation time but it will become relevant for 368c2ecf20Sopenharmony_ci * accelerated X later 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_civoid psb_spank(struct drm_psb_private *dev_priv) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | 418c2ecf20Sopenharmony_ci _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | 428c2ecf20Sopenharmony_ci _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET | 438c2ecf20Sopenharmony_ci _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET); 448c2ecf20Sopenharmony_ci PSB_RSGX32(PSB_CR_SOFT_RESET); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci msleep(1); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci PSB_WSGX32(0, PSB_CR_SOFT_RESET); 498c2ecf20Sopenharmony_ci wmb(); 508c2ecf20Sopenharmony_ci PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT, 518c2ecf20Sopenharmony_ci PSB_CR_BIF_CTRL); 528c2ecf20Sopenharmony_ci wmb(); 538c2ecf20Sopenharmony_ci (void) PSB_RSGX32(PSB_CR_BIF_CTRL); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci msleep(1); 568c2ecf20Sopenharmony_ci PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT, 578c2ecf20Sopenharmony_ci PSB_CR_BIF_CTRL); 588c2ecf20Sopenharmony_ci (void) PSB_RSGX32(PSB_CR_BIF_CTRL); 598c2ecf20Sopenharmony_ci PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/** 638c2ecf20Sopenharmony_ci * psb2_2d_wait_available - wait for FIFO room 648c2ecf20Sopenharmony_ci * @dev_priv: our DRM device 658c2ecf20Sopenharmony_ci * @size: size (in dwords) of the command we want to issue 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * Wait until there is room to load the FIFO with our data. If the 688c2ecf20Sopenharmony_ci * device is not responding then reset it 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_cistatic int psb_2d_wait_available(struct drm_psb_private *dev_priv, 718c2ecf20Sopenharmony_ci unsigned size) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF); 748c2ecf20Sopenharmony_ci unsigned long t = jiffies + HZ; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci while (avail < size) { 778c2ecf20Sopenharmony_ci avail = PSB_RSGX32(PSB_CR_2D_SOCIF); 788c2ecf20Sopenharmony_ci if (time_after(jiffies, t)) { 798c2ecf20Sopenharmony_ci psb_spank(dev_priv); 808c2ecf20Sopenharmony_ci return -EIO; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci return 0; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/** 878c2ecf20Sopenharmony_ci * psb_2d_submit - submit a 2D command 888c2ecf20Sopenharmony_ci * @dev_priv: our DRM device 898c2ecf20Sopenharmony_ci * @cmdbuf: command to issue 908c2ecf20Sopenharmony_ci * @size: length (in dwords) 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * Issue one or more 2D commands to the accelerator. This needs to be 938c2ecf20Sopenharmony_ci * serialized later when we add the GEM interfaces for acceleration 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_cistatic int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, 968c2ecf20Sopenharmony_ci unsigned size) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci int ret = 0; 998c2ecf20Sopenharmony_ci int i; 1008c2ecf20Sopenharmony_ci unsigned submit_size; 1018c2ecf20Sopenharmony_ci unsigned long flags; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev_priv->lock_2d, flags); 1048c2ecf20Sopenharmony_ci while (size > 0) { 1058c2ecf20Sopenharmony_ci submit_size = (size < 0x60) ? size : 0x60; 1068c2ecf20Sopenharmony_ci size -= submit_size; 1078c2ecf20Sopenharmony_ci ret = psb_2d_wait_available(dev_priv, submit_size); 1088c2ecf20Sopenharmony_ci if (ret) 1098c2ecf20Sopenharmony_ci break; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci submit_size <<= 2; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci for (i = 0; i < submit_size; i += 4) 1148c2ecf20Sopenharmony_ci PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev_priv->lock_2d, flags); 1198c2ecf20Sopenharmony_ci return ret; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/** 1248c2ecf20Sopenharmony_ci * psb_accel_2d_copy_direction - compute blit order 1258c2ecf20Sopenharmony_ci * @xdir: X direction of move 1268c2ecf20Sopenharmony_ci * @ydir: Y direction of move 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * Compute the correct order setings to ensure that an overlapping blit 1298c2ecf20Sopenharmony_ci * correctly copies all the pixels. 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_cistatic u32 psb_accel_2d_copy_direction(int xdir, int ydir) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci if (xdir < 0) 1348c2ecf20Sopenharmony_ci return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL : 1358c2ecf20Sopenharmony_ci PSB_2D_COPYORDER_TR2BL; 1368c2ecf20Sopenharmony_ci else 1378c2ecf20Sopenharmony_ci return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR : 1388c2ecf20Sopenharmony_ci PSB_2D_COPYORDER_TL2BR; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/** 1428c2ecf20Sopenharmony_ci * psb_accel_2d_copy - accelerated 2D copy 1438c2ecf20Sopenharmony_ci * @dev_priv: our DRM device 1448c2ecf20Sopenharmony_ci * @src_offset in bytes 1458c2ecf20Sopenharmony_ci * @src_stride in bytes 1468c2ecf20Sopenharmony_ci * @src_format psb 2D format defines 1478c2ecf20Sopenharmony_ci * @dst_offset in bytes 1488c2ecf20Sopenharmony_ci * @dst_stride in bytes 1498c2ecf20Sopenharmony_ci * @dst_format psb 2D format defines 1508c2ecf20Sopenharmony_ci * @src_x offset in pixels 1518c2ecf20Sopenharmony_ci * @src_y offset in pixels 1528c2ecf20Sopenharmony_ci * @dst_x offset in pixels 1538c2ecf20Sopenharmony_ci * @dst_y offset in pixels 1548c2ecf20Sopenharmony_ci * @size_x of the copied area 1558c2ecf20Sopenharmony_ci * @size_y of the copied area 1568c2ecf20Sopenharmony_ci * 1578c2ecf20Sopenharmony_ci * Format and issue a 2D accelerated copy command. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_cistatic int psb_accel_2d_copy(struct drm_psb_private *dev_priv, 1608c2ecf20Sopenharmony_ci uint32_t src_offset, uint32_t src_stride, 1618c2ecf20Sopenharmony_ci uint32_t src_format, uint32_t dst_offset, 1628c2ecf20Sopenharmony_ci uint32_t dst_stride, uint32_t dst_format, 1638c2ecf20Sopenharmony_ci uint16_t src_x, uint16_t src_y, 1648c2ecf20Sopenharmony_ci uint16_t dst_x, uint16_t dst_y, 1658c2ecf20Sopenharmony_ci uint16_t size_x, uint16_t size_y) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci uint32_t blit_cmd; 1688c2ecf20Sopenharmony_ci uint32_t buffer[10]; 1698c2ecf20Sopenharmony_ci uint32_t *buf; 1708c2ecf20Sopenharmony_ci uint32_t direction; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci buf = buffer; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci direction = 1758c2ecf20Sopenharmony_ci psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci if (direction == PSB_2D_COPYORDER_BR2TL || 1788c2ecf20Sopenharmony_ci direction == PSB_2D_COPYORDER_TR2BL) { 1798c2ecf20Sopenharmony_ci src_x += size_x - 1; 1808c2ecf20Sopenharmony_ci dst_x += size_x - 1; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci if (direction == PSB_2D_COPYORDER_BR2TL || 1838c2ecf20Sopenharmony_ci direction == PSB_2D_COPYORDER_BL2TR) { 1848c2ecf20Sopenharmony_ci src_y += size_y - 1; 1858c2ecf20Sopenharmony_ci dst_y += size_y - 1; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci blit_cmd = 1898c2ecf20Sopenharmony_ci PSB_2D_BLIT_BH | 1908c2ecf20Sopenharmony_ci PSB_2D_ROT_NONE | 1918c2ecf20Sopenharmony_ci PSB_2D_DSTCK_DISABLE | 1928c2ecf20Sopenharmony_ci PSB_2D_SRCCK_DISABLE | 1938c2ecf20Sopenharmony_ci PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci *buf++ = PSB_2D_FENCE_BH; 1968c2ecf20Sopenharmony_ci *buf++ = 1978c2ecf20Sopenharmony_ci PSB_2D_DST_SURF_BH | dst_format | (dst_stride << 1988c2ecf20Sopenharmony_ci PSB_2D_DST_STRIDE_SHIFT); 1998c2ecf20Sopenharmony_ci *buf++ = dst_offset; 2008c2ecf20Sopenharmony_ci *buf++ = 2018c2ecf20Sopenharmony_ci PSB_2D_SRC_SURF_BH | src_format | (src_stride << 2028c2ecf20Sopenharmony_ci PSB_2D_SRC_STRIDE_SHIFT); 2038c2ecf20Sopenharmony_ci *buf++ = src_offset; 2048c2ecf20Sopenharmony_ci *buf++ = 2058c2ecf20Sopenharmony_ci PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) | 2068c2ecf20Sopenharmony_ci (src_y << PSB_2D_SRCOFF_YSTART_SHIFT); 2078c2ecf20Sopenharmony_ci *buf++ = blit_cmd; 2088c2ecf20Sopenharmony_ci *buf++ = 2098c2ecf20Sopenharmony_ci (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y << 2108c2ecf20Sopenharmony_ci PSB_2D_DST_YSTART_SHIFT); 2118c2ecf20Sopenharmony_ci *buf++ = 2128c2ecf20Sopenharmony_ci (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y << 2138c2ecf20Sopenharmony_ci PSB_2D_DST_YSIZE_SHIFT); 2148c2ecf20Sopenharmony_ci *buf++ = PSB_2D_FLUSH_BH; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return psbfb_2d_submit(dev_priv, buffer, buf - buffer); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/** 2208c2ecf20Sopenharmony_ci * psbfb_copyarea_accel - copyarea acceleration for /dev/fb 2218c2ecf20Sopenharmony_ci * @info: our framebuffer 2228c2ecf20Sopenharmony_ci * @a: copyarea parameters from the framebuffer core 2238c2ecf20Sopenharmony_ci * 2248c2ecf20Sopenharmony_ci * Perform a 2D copy via the accelerator 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_cistatic void psbfb_copyarea_accel(struct fb_info *info, 2278c2ecf20Sopenharmony_ci const struct fb_copyarea *a) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct drm_fb_helper *fb_helper = info->par; 2308c2ecf20Sopenharmony_ci struct drm_framebuffer *fb = fb_helper->fb; 2318c2ecf20Sopenharmony_ci struct drm_device *dev; 2328c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv; 2338c2ecf20Sopenharmony_ci uint32_t offset; 2348c2ecf20Sopenharmony_ci uint32_t stride; 2358c2ecf20Sopenharmony_ci uint32_t src_format; 2368c2ecf20Sopenharmony_ci uint32_t dst_format; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (!fb) 2398c2ecf20Sopenharmony_ci return; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci dev = fb->dev; 2428c2ecf20Sopenharmony_ci dev_priv = dev->dev_private; 2438c2ecf20Sopenharmony_ci offset = to_gtt_range(fb->obj[0])->offset; 2448c2ecf20Sopenharmony_ci stride = fb->pitches[0]; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci switch (fb->format->depth) { 2478c2ecf20Sopenharmony_ci case 8: 2488c2ecf20Sopenharmony_ci src_format = PSB_2D_SRC_332RGB; 2498c2ecf20Sopenharmony_ci dst_format = PSB_2D_DST_332RGB; 2508c2ecf20Sopenharmony_ci break; 2518c2ecf20Sopenharmony_ci case 15: 2528c2ecf20Sopenharmony_ci src_format = PSB_2D_SRC_555RGB; 2538c2ecf20Sopenharmony_ci dst_format = PSB_2D_DST_555RGB; 2548c2ecf20Sopenharmony_ci break; 2558c2ecf20Sopenharmony_ci case 16: 2568c2ecf20Sopenharmony_ci src_format = PSB_2D_SRC_565RGB; 2578c2ecf20Sopenharmony_ci dst_format = PSB_2D_DST_565RGB; 2588c2ecf20Sopenharmony_ci break; 2598c2ecf20Sopenharmony_ci case 24: 2608c2ecf20Sopenharmony_ci case 32: 2618c2ecf20Sopenharmony_ci /* this is wrong but since we don't do blending its okay */ 2628c2ecf20Sopenharmony_ci src_format = PSB_2D_SRC_8888ARGB; 2638c2ecf20Sopenharmony_ci dst_format = PSB_2D_DST_8888ARGB; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci default: 2668c2ecf20Sopenharmony_ci /* software fallback */ 2678c2ecf20Sopenharmony_ci drm_fb_helper_cfb_copyarea(info, a); 2688c2ecf20Sopenharmony_ci return; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (!gma_power_begin(dev, false)) { 2728c2ecf20Sopenharmony_ci drm_fb_helper_cfb_copyarea(info, a); 2738c2ecf20Sopenharmony_ci return; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci psb_accel_2d_copy(dev_priv, 2768c2ecf20Sopenharmony_ci offset, stride, src_format, 2778c2ecf20Sopenharmony_ci offset, stride, dst_format, 2788c2ecf20Sopenharmony_ci a->sx, a->sy, a->dx, a->dy, a->width, a->height); 2798c2ecf20Sopenharmony_ci gma_power_end(dev); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/** 2838c2ecf20Sopenharmony_ci * psbfb_copyarea - 2D copy interface 2848c2ecf20Sopenharmony_ci * @info: our framebuffer 2858c2ecf20Sopenharmony_ci * @region: region to copy 2868c2ecf20Sopenharmony_ci * 2878c2ecf20Sopenharmony_ci * Copy an area of the framebuffer console either by the accelerator 2888c2ecf20Sopenharmony_ci * or directly using the cfb helpers according to the request 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_civoid psbfb_copyarea(struct fb_info *info, 2918c2ecf20Sopenharmony_ci const struct fb_copyarea *region) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci if (unlikely(info->state != FBINFO_STATE_RUNNING)) 2948c2ecf20Sopenharmony_ci return; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* Avoid the 8 pixel erratum */ 2978c2ecf20Sopenharmony_ci if (region->width == 8 || region->height == 8 || 2988c2ecf20Sopenharmony_ci (info->flags & FBINFO_HWACCEL_DISABLED)) 2998c2ecf20Sopenharmony_ci return drm_fb_helper_cfb_copyarea(info, region); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci psbfb_copyarea_accel(info, region); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci/** 3058c2ecf20Sopenharmony_ci * psbfb_sync - synchronize 2D 3068c2ecf20Sopenharmony_ci * @info: our framebuffer 3078c2ecf20Sopenharmony_ci * 3088c2ecf20Sopenharmony_ci * Wait for the 2D engine to quiesce so that we can do CPU 3098c2ecf20Sopenharmony_ci * access to the framebuffer again 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_ciint psbfb_sync(struct fb_info *info) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct drm_fb_helper *fb_helper = info->par; 3148c2ecf20Sopenharmony_ci struct drm_framebuffer *fb = fb_helper->fb; 3158c2ecf20Sopenharmony_ci struct drm_device *dev = fb->dev; 3168c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 3178c2ecf20Sopenharmony_ci unsigned long _end = jiffies + HZ; 3188c2ecf20Sopenharmony_ci int busy = 0; 3198c2ecf20Sopenharmony_ci unsigned long flags; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev_priv->lock_2d, flags); 3228c2ecf20Sopenharmony_ci /* 3238c2ecf20Sopenharmony_ci * First idle the 2D engine. 3248c2ecf20Sopenharmony_ci */ 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) && 3278c2ecf20Sopenharmony_ci ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0)) 3288c2ecf20Sopenharmony_ci goto out; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci do { 3318c2ecf20Sopenharmony_ci busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); 3328c2ecf20Sopenharmony_ci cpu_relax(); 3338c2ecf20Sopenharmony_ci } while (busy && !time_after_eq(jiffies, _end)); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (busy) 3368c2ecf20Sopenharmony_ci busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); 3378c2ecf20Sopenharmony_ci if (busy) 3388c2ecf20Sopenharmony_ci goto out; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci do { 3418c2ecf20Sopenharmony_ci busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & 3428c2ecf20Sopenharmony_ci _PSB_C2B_STATUS_BUSY) != 0); 3438c2ecf20Sopenharmony_ci cpu_relax(); 3448c2ecf20Sopenharmony_ci } while (busy && !time_after_eq(jiffies, _end)); 3458c2ecf20Sopenharmony_ci if (busy) 3468c2ecf20Sopenharmony_ci busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & 3478c2ecf20Sopenharmony_ci _PSB_C2B_STATUS_BUSY) != 0); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ciout: 3508c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev_priv->lock_2d, flags); 3518c2ecf20Sopenharmony_ci return (busy) ? -EBUSY : 0; 3528c2ecf20Sopenharmony_ci} 353