Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright 2013 Matrox Graphics
  4 *
 
 
 
 
  5 * Author: Christopher Harvey <charvey@matrox.com>
  6 */
  7
  8#include <drm/drm_pci.h>
  9
 10#include "mgag200_drv.h"
 11
 12static bool warn_transparent = true;
 13static bool warn_palette = true;
 14
 15/*
 16  Hide the cursor off screen. We can't disable the cursor hardware because it
 17  takes too long to re-activate and causes momentary corruption
 18*/
 19static void mga_hide_cursor(struct mga_device *mdev)
 20{
 21	WREG8(MGA_CURPOSXL, 0);
 22	WREG8(MGA_CURPOSXH, 0);
 23	if (mdev->cursor.pixels_current)
 24		drm_gem_vram_unpin(mdev->cursor.pixels_current);
 25	mdev->cursor.pixels_current = NULL;
 
 26}
 27
 28int mga_crtc_cursor_set(struct drm_crtc *crtc,
 29			struct drm_file *file_priv,
 30			uint32_t handle,
 31			uint32_t width,
 32			uint32_t height)
 33{
 34	struct drm_device *dev = crtc->dev;
 35	struct mga_device *mdev = (struct mga_device *)dev->dev_private;
 36	struct drm_gem_vram_object *pixels_1 = mdev->cursor.pixels_1;
 37	struct drm_gem_vram_object *pixels_2 = mdev->cursor.pixels_2;
 38	struct drm_gem_vram_object *pixels_current = mdev->cursor.pixels_current;
 39	struct drm_gem_vram_object *pixels_next;
 40	struct drm_gem_object *obj;
 41	struct drm_gem_vram_object *gbo = NULL;
 42	int ret = 0;
 43	u8 *src, *dst;
 44	unsigned int i, row, col;
 45	uint32_t colour_set[16];
 46	uint32_t *next_space = &colour_set[0];
 47	uint32_t *palette_iter;
 48	uint32_t this_colour;
 49	bool found = false;
 50	int colour_count = 0;
 51	s64 gpu_addr;
 52	u64 dst_gpu;
 53	u8 reg_index;
 54	u8 this_row[48];
 55
 56	if (!pixels_1 || !pixels_2) {
 57		WREG8(MGA_CURPOSXL, 0);
 58		WREG8(MGA_CURPOSXH, 0);
 59		return -ENOTSUPP; /* Didn't allocate space for cursors */
 60	}
 61
 62	if (WARN_ON(pixels_current &&
 63		    pixels_1 != pixels_current &&
 64		    pixels_2 != pixels_current)) {
 65		return -ENOTSUPP; /* inconsistent state */
 66	}
 67
 
 
 
 
 68	if (!handle || !file_priv) {
 69		mga_hide_cursor(mdev);
 70		return 0;
 71	}
 72
 73	if (width != 64 || height != 64) {
 74		WREG8(MGA_CURPOSXL, 0);
 75		WREG8(MGA_CURPOSXH, 0);
 76		return -EINVAL;
 77	}
 78
 79	if (pixels_current == pixels_1)
 80		pixels_next = pixels_2;
 81	else
 82		pixels_next = pixels_1;
 83
 84	obj = drm_gem_object_lookup(file_priv, handle);
 85	if (!obj)
 86		return -ENOENT;
 87	gbo = drm_gem_vram_of_gem(obj);
 88	ret = drm_gem_vram_pin(gbo, 0);
 
 
 
 
 
 
 89	if (ret) {
 90		dev_err(&dev->pdev->dev, "failed to lock user bo\n");
 91		goto err_drm_gem_object_put_unlocked;
 
 
 92	}
 93	src = drm_gem_vram_kmap(gbo, true, NULL);
 94	if (IS_ERR(src)) {
 95		ret = PTR_ERR(src);
 96		dev_err(&dev->pdev->dev,
 97			"failed to kmap user buffer updates\n");
 98		goto err_drm_gem_vram_unpin_src;
 
 
 
 
 
 
 
 
 
 99	}
100
101	/* Pin and map up-coming buffer to write colour indices */
102	ret = drm_gem_vram_pin(pixels_next, DRM_GEM_VRAM_PL_FLAG_VRAM);
103	if (ret) {
104		dev_err(&dev->pdev->dev,
105			"failed to pin cursor buffer: %d\n", ret);
106		goto err_drm_gem_vram_kunmap_src;
107	}
108	dst = drm_gem_vram_kmap(pixels_next, true, NULL);
109	if (IS_ERR(dst)) {
110		ret = PTR_ERR(dst);
111		dev_err(&dev->pdev->dev,
112			"failed to kmap cursor updates: %d\n", ret);
113		goto err_drm_gem_vram_unpin_dst;
114	}
115	gpu_addr = drm_gem_vram_offset(pixels_next);
116	if (gpu_addr < 0) {
117		ret = (int)gpu_addr;
118		dev_err(&dev->pdev->dev,
119			"failed to get cursor scanout address: %d\n", ret);
120		goto err_drm_gem_vram_kunmap_dst;
121	}
122	dst_gpu = (u64)gpu_addr;
123
124	memset(&colour_set[0], 0, sizeof(uint32_t)*16);
125	/* width*height*4 = 16384 */
126	for (i = 0; i < 16384; i += 4) {
127		this_colour = ioread32(src + i);
128		/* No transparency */
129		if (this_colour>>24 != 0xff &&
130			this_colour>>24 != 0x0) {
131			if (warn_transparent) {
132				dev_info(&dev->pdev->dev, "Video card doesn't support cursors with partial transparency.\n");
133				dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
134				warn_transparent = false; /* Only tell the user once. */
135			}
136			ret = -EINVAL;
137			goto err_drm_gem_vram_kunmap_dst;
138		}
139		/* Don't need to store transparent pixels as colours */
140		if (this_colour>>24 == 0x0)
141			continue;
142		found = false;
143		for (palette_iter = &colour_set[0]; palette_iter != next_space; palette_iter++) {
144			if (*palette_iter == this_colour) {
145				found = true;
146				break;
147			}
148		}
149		if (found)
150			continue;
151		/* We only support 4bit paletted cursors */
152		if (colour_count >= 16) {
153			if (warn_palette) {
154				dev_info(&dev->pdev->dev, "Video card only supports cursors with up to 16 colours.\n");
155				dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
156				warn_palette = false; /* Only tell the user once. */
157			}
158			ret = -EINVAL;
159			goto err_drm_gem_vram_kunmap_dst;
160		}
161		*next_space = this_colour;
162		next_space++;
163		colour_count++;
164	}
165
166	/* Program colours from cursor icon into palette */
167	for (i = 0; i < colour_count; i++) {
168		if (i <= 2)
169			reg_index = 0x8 + i*0x4;
170		else
171			reg_index = 0x60 + i*0x3;
172		WREG_DAC(reg_index, colour_set[i] & 0xff);
173		WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff);
174		WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff);
175		BUG_ON((colour_set[i]>>24 & 0xff) != 0xff);
176	}
177
 
 
 
 
 
 
 
 
 
 
 
178	/* now write colour indices into hardware cursor buffer */
179	for (row = 0; row < 64; row++) {
180		memset(&this_row[0], 0, 48);
181		for (col = 0; col < 64; col++) {
182			this_colour = ioread32(src + 4*(col + 64*row));
183			/* write transparent pixels */
184			if (this_colour>>24 == 0x0) {
185				this_row[47 - col/8] |= 0x80>>(col%8);
186				continue;
187			}
188
189			/* write colour index here */
190			for (i = 0; i < colour_count; i++) {
191				if (colour_set[i] == this_colour) {
192					if (col % 2)
193						this_row[col/2] |= i<<4;
194					else
195						this_row[col/2] |= i;
196					break;
197				}
198			}
199		}
200		memcpy_toio(dst + row*48, &this_row[0], 48);
201	}
202
203	/* Program gpu address of cursor buffer */
204	WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW, (u8)((dst_gpu>>10) & 0xff));
205	WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI, (u8)((dst_gpu>>18) & 0x3f));
 
 
 
 
206
207	/* Adjust cursor control register to turn on the cursor */
208	WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */
209
210	/* Now update internal buffer pointers */
211	if (pixels_current)
212		drm_gem_vram_unpin(pixels_current);
213	mdev->cursor.pixels_current = pixels_next;
214
215	drm_gem_vram_kunmap(pixels_next);
216	drm_gem_vram_kunmap(gbo);
217	drm_gem_vram_unpin(gbo);
218	drm_gem_object_put_unlocked(obj);
219
220	return 0;
221
222err_drm_gem_vram_kunmap_dst:
223	drm_gem_vram_kunmap(pixels_next);
224err_drm_gem_vram_unpin_dst:
225	drm_gem_vram_unpin(pixels_next);
226err_drm_gem_vram_kunmap_src:
227	drm_gem_vram_kunmap(gbo);
228err_drm_gem_vram_unpin_src:
229	drm_gem_vram_unpin(gbo);
230err_drm_gem_object_put_unlocked:
231	drm_gem_object_put_unlocked(obj);
 
 
 
 
232	return ret;
233}
234
235int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
236{
237	struct mga_device *mdev = (struct mga_device *)crtc->dev->dev_private;
238	/* Our origin is at (64,64) */
239	x += 64;
240	y += 64;
241
242	BUG_ON(x <= 0);
243	BUG_ON(y <= 0);
244	BUG_ON(x & ~0xffff);
245	BUG_ON(y & ~0xffff);
246
247	WREG8(MGA_CURPOSXL, x & 0xff);
248	WREG8(MGA_CURPOSXH, (x>>8) & 0xff);
249
250	WREG8(MGA_CURPOSYL, y & 0xff);
251	WREG8(MGA_CURPOSYH, (y>>8) & 0xff);
252	return 0;
253}
v4.10.11
 
  1/*
  2 * Copyright 2013 Matrox Graphics
  3 *
  4 * This file is subject to the terms and conditions of the GNU General
  5 * Public License version 2. See the file COPYING in the main
  6 * directory of this archive for more details.
  7 *
  8 * Author: Christopher Harvey <charvey@matrox.com>
  9 */
 10
 11#include <drm/drmP.h>
 
 12#include "mgag200_drv.h"
 13
 14static bool warn_transparent = true;
 15static bool warn_palette = true;
 16
 17/*
 18  Hide the cursor off screen. We can't disable the cursor hardware because it
 19  takes too long to re-activate and causes momentary corruption
 20*/
 21static void mga_hide_cursor(struct mga_device *mdev)
 22{
 23	WREG8(MGA_CURPOSXL, 0);
 24	WREG8(MGA_CURPOSXH, 0);
 25	if (mdev->cursor.pixels_1->pin_count)
 26		mgag200_bo_unpin(mdev->cursor.pixels_1);
 27	if (mdev->cursor.pixels_2->pin_count)
 28		mgag200_bo_unpin(mdev->cursor.pixels_2);
 29}
 30
 31int mga_crtc_cursor_set(struct drm_crtc *crtc,
 32			struct drm_file *file_priv,
 33			uint32_t handle,
 34			uint32_t width,
 35			uint32_t height)
 36{
 37	struct drm_device *dev = crtc->dev;
 38	struct mga_device *mdev = (struct mga_device *)dev->dev_private;
 39	struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1;
 40	struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2;
 41	struct mgag200_bo *pixels_current = mdev->cursor.pixels_current;
 42	struct mgag200_bo *pixels_prev = mdev->cursor.pixels_prev;
 43	struct drm_gem_object *obj;
 44	struct mgag200_bo *bo = NULL;
 45	int ret = 0;
 
 46	unsigned int i, row, col;
 47	uint32_t colour_set[16];
 48	uint32_t *next_space = &colour_set[0];
 49	uint32_t *palette_iter;
 50	uint32_t this_colour;
 51	bool found = false;
 52	int colour_count = 0;
 53	u64 gpu_addr;
 
 54	u8 reg_index;
 55	u8 this_row[48];
 56
 57	if (!pixels_1 || !pixels_2) {
 58		WREG8(MGA_CURPOSXL, 0);
 59		WREG8(MGA_CURPOSXH, 0);
 60		return -ENOTSUPP; /* Didn't allocate space for cursors */
 61	}
 62
 63	if ((width != 64 || height != 64) && handle) {
 64		WREG8(MGA_CURPOSXL, 0);
 65		WREG8(MGA_CURPOSXH, 0);
 66		return -EINVAL;
 67	}
 68
 69	BUG_ON(pixels_1 != pixels_current && pixels_1 != pixels_prev);
 70	BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
 71	BUG_ON(pixels_current == pixels_prev);
 72
 73	if (!handle || !file_priv) {
 74		mga_hide_cursor(mdev);
 75		return 0;
 76	}
 77
 
 
 
 
 
 
 
 
 
 
 
 78	obj = drm_gem_object_lookup(file_priv, handle);
 79	if (!obj)
 80		return -ENOENT;
 81
 82	ret = mgag200_bo_reserve(pixels_1, true);
 83	if (ret) {
 84		WREG8(MGA_CURPOSXL, 0);
 85		WREG8(MGA_CURPOSXH, 0);
 86		goto out_unref;
 87	}
 88	ret = mgag200_bo_reserve(pixels_2, true);
 89	if (ret) {
 90		WREG8(MGA_CURPOSXL, 0);
 91		WREG8(MGA_CURPOSXH, 0);
 92		mgag200_bo_unreserve(pixels_1);
 93		goto out_unreserve1;
 94	}
 95
 96	/* Move cursor buffers into VRAM if they aren't already */
 97	if (!pixels_1->pin_count) {
 98		ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM,
 99				     &mdev->cursor.pixels_1_gpu_addr);
100		if (ret)
101			goto out1;
102	}
103	if (!pixels_2->pin_count) {
104		ret = mgag200_bo_pin(pixels_2, TTM_PL_FLAG_VRAM,
105				     &mdev->cursor.pixels_2_gpu_addr);
106		if (ret) {
107			mgag200_bo_unpin(pixels_1);
108			goto out1;
109		}
110	}
111
112	bo = gem_to_mga_bo(obj);
113	ret = mgag200_bo_reserve(bo, true);
114	if (ret) {
115		dev_err(&dev->pdev->dev, "failed to reserve user bo\n");
116		goto out1;
117	}
118	if (!bo->kmap.virtual) {
119		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
120		if (ret) {
121			dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n");
122			goto out2;
123		}
 
 
 
 
 
 
 
 
124	}
 
125
126	memset(&colour_set[0], 0, sizeof(uint32_t)*16);
127	/* width*height*4 = 16384 */
128	for (i = 0; i < 16384; i += 4) {
129		this_colour = ioread32(bo->kmap.virtual + i);
130		/* No transparency */
131		if (this_colour>>24 != 0xff &&
132			this_colour>>24 != 0x0) {
133			if (warn_transparent) {
134				dev_info(&dev->pdev->dev, "Video card doesn't support cursors with partial transparency.\n");
135				dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
136				warn_transparent = false; /* Only tell the user once. */
137			}
138			ret = -EINVAL;
139			goto out3;
140		}
141		/* Don't need to store transparent pixels as colours */
142		if (this_colour>>24 == 0x0)
143			continue;
144		found = false;
145		for (palette_iter = &colour_set[0]; palette_iter != next_space; palette_iter++) {
146			if (*palette_iter == this_colour) {
147				found = true;
148				break;
149			}
150		}
151		if (found)
152			continue;
153		/* We only support 4bit paletted cursors */
154		if (colour_count >= 16) {
155			if (warn_palette) {
156				dev_info(&dev->pdev->dev, "Video card only supports cursors with up to 16 colours.\n");
157				dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
158				warn_palette = false; /* Only tell the user once. */
159			}
160			ret = -EINVAL;
161			goto out3;
162		}
163		*next_space = this_colour;
164		next_space++;
165		colour_count++;
166	}
167
168	/* Program colours from cursor icon into palette */
169	for (i = 0; i < colour_count; i++) {
170		if (i <= 2)
171			reg_index = 0x8 + i*0x4;
172		else
173			reg_index = 0x60 + i*0x3;
174		WREG_DAC(reg_index, colour_set[i] & 0xff);
175		WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff);
176		WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff);
177		BUG_ON((colour_set[i]>>24 & 0xff) != 0xff);
178	}
179
180	/* Map up-coming buffer to write colour indices */
181	if (!pixels_prev->kmap.virtual) {
182		ret = ttm_bo_kmap(&pixels_prev->bo, 0,
183				  pixels_prev->bo.num_pages,
184				  &pixels_prev->kmap);
185		if (ret) {
186			dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n");
187			goto out3;
188		}
189	}
190
191	/* now write colour indices into hardware cursor buffer */
192	for (row = 0; row < 64; row++) {
193		memset(&this_row[0], 0, 48);
194		for (col = 0; col < 64; col++) {
195			this_colour = ioread32(bo->kmap.virtual + 4*(col + 64*row));
196			/* write transparent pixels */
197			if (this_colour>>24 == 0x0) {
198				this_row[47 - col/8] |= 0x80>>(col%8);
199				continue;
200			}
201
202			/* write colour index here */
203			for (i = 0; i < colour_count; i++) {
204				if (colour_set[i] == this_colour) {
205					if (col % 2)
206						this_row[col/2] |= i<<4;
207					else
208						this_row[col/2] |= i;
209					break;
210				}
211			}
212		}
213		memcpy_toio(pixels_prev->kmap.virtual + row*48, &this_row[0], 48);
214	}
215
216	/* Program gpu address of cursor buffer */
217	if (pixels_prev == pixels_1)
218		gpu_addr = mdev->cursor.pixels_1_gpu_addr;
219	else
220		gpu_addr = mdev->cursor.pixels_2_gpu_addr;
221	WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW, (u8)((gpu_addr>>10) & 0xff));
222	WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI, (u8)((gpu_addr>>18) & 0x3f));
223
224	/* Adjust cursor control register to turn on the cursor */
225	WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */
226
227	/* Now swap internal buffer pointers */
228	if (mdev->cursor.pixels_1 == mdev->cursor.pixels_prev) {
229		mdev->cursor.pixels_prev = mdev->cursor.pixels_2;
230		mdev->cursor.pixels_current = mdev->cursor.pixels_1;
231	} else if (mdev->cursor.pixels_1 == mdev->cursor.pixels_current) {
232		mdev->cursor.pixels_prev = mdev->cursor.pixels_1;
233		mdev->cursor.pixels_current = mdev->cursor.pixels_2;
234	} else {
235		BUG();
236	}
237	ret = 0;
238
239	ttm_bo_kunmap(&pixels_prev->kmap);
240 out3:
241	ttm_bo_kunmap(&bo->kmap);
242 out2:
243	mgag200_bo_unreserve(bo);
244 out1:
245	if (ret)
246		mga_hide_cursor(mdev);
247	mgag200_bo_unreserve(pixels_1);
248out_unreserve1:
249	mgag200_bo_unreserve(pixels_2);
250out_unref:
251	drm_gem_object_unreference_unlocked(obj);
252
253	return ret;
254}
255
256int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
257{
258	struct mga_device *mdev = (struct mga_device *)crtc->dev->dev_private;
259	/* Our origin is at (64,64) */
260	x += 64;
261	y += 64;
262
263	BUG_ON(x <= 0);
264	BUG_ON(y <= 0);
265	BUG_ON(x & ~0xffff);
266	BUG_ON(y & ~0xffff);
267
268	WREG8(MGA_CURPOSXL, x & 0xff);
269	WREG8(MGA_CURPOSXH, (x>>8) & 0xff);
270
271	WREG8(MGA_CURPOSYL, y & 0xff);
272	WREG8(MGA_CURPOSYH, (y>>8) & 0xff);
273	return 0;
274}