Skip to content
This repository was archived by the owner on Jan 27, 2026. It is now read-only.

Commit 280303a

Browse files
committed
Support backlight device in virtio gpu
Enable virtio backlight function, it will expose sysfs node /sys/class/backlight/virtio-gpu-backlight0 for guest user. Test-done: - iGPU VF + virtio-GPU; - backlight setting through command Tracked-On: OAM-117147 Signed-off-by: Xue, Bosheng <bosheng.xue@intel.com>
1 parent bd445d6 commit 280303a

6 files changed

Lines changed: 282 additions & 0 deletions

File tree

drivers/gpu/drm/virtio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config DRM_VIRTIO_GPU
66
select DRM_KMS_HELPER
77
select DRM_GEM_SHMEM_HELPER
88
select VIRTIO_DMA_SHARED_BUFFER
9+
select BACKLIGHT_CLASS_DEVICE
910
help
1011
This is the virtual GPU driver for virtio. It can be used with
1112
QEMU based VMMs (like KVM or Xen).

drivers/gpu/drm/virtio/virtgpu_drv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static unsigned int features[] = {
165165
VIRTIO_GPU_F_MODIFIER,
166166
VIRTIO_GPU_F_SCALING,
167167
VIRTIO_GPU_F_VBLANK,
168+
VIRTIO_GPU_F_BACKLIGHT,
168169
VIRTIO_GPU_F_ALLOW_P2P,
169170
VIRTIO_GPU_F_MULTI_PLANE,
170171
VIRTIO_GPU_F_ROTATION,

drivers/gpu/drm/virtio/virtgpu_drv.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/virtio_ids.h>
3232
#include <linux/virtio_config.h>
3333
#include <linux/virtio_gpu.h>
34+
#include <linux/backlight.h>
3435

3536
#include <drm/drm_atomic.h>
3637
#include <drm/drm_drv.h>
@@ -175,6 +176,7 @@ struct virtio_gpu_vbuffer {
175176
struct list_head list;
176177

177178
uint32_t seqno;
179+
struct completion notify;
178180
};
179181

180182
#define VIRTIO_GPU_MAX_PLANES 6
@@ -232,12 +234,26 @@ struct virtio_gpu_vblank {
232234
uint32_t buf[4];
233235
};
234236

237+
#define MAX_BACKLIGHT_NUM 16
238+
struct virtio_gpu_backlight {
239+
struct virtio_gpu_device *vgdev;
240+
struct backlight_device *bd;
241+
uint32_t backlight_id;
242+
int32_t brightness;
243+
int32_t max_brightness;
244+
int32_t power;
245+
enum backlight_type type;
246+
enum backlight_scale scale;
247+
};
248+
235249
struct virtio_gpu_device {
236250
struct drm_device *ddev;
237251

238252
struct virtio_device *vdev;
239253

240254
struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS];
255+
struct virtio_gpu_backlight backlight[MAX_BACKLIGHT_NUM];
256+
uint32_t num_backlight;
241257
uint32_t num_scanouts;
242258
uint32_t num_vblankq;
243259
struct virtio_gpu_queue ctrlq;
@@ -263,6 +279,7 @@ struct virtio_gpu_device {
263279
bool has_modifier;
264280
bool has_scaling;
265281
bool has_vblank;
282+
bool has_backlight;
266283
bool has_allow_p2p;
267284
bool has_multi_plane;
268285
bool has_rotation;
@@ -490,6 +507,15 @@ void virtio_gpu_cmd_set_scaling(struct virtio_gpu_device *vgdev,
490507
void virtio_gpu_cmd_send_misc(struct virtio_gpu_device *vgdev, uint32_t scanout_id,
491508
uint32_t plane_indx, struct virtio_gpu_cmd *cmdp, int cnt);
492509

510+
int virtio_gpu_cmd_backlight_update_status(struct virtio_gpu_device *vgdev,
511+
uint32_t backlight_id);
512+
513+
int virtio_gpu_cmd_get_brightness(struct virtio_gpu_device *vgdev,
514+
uint32_t backlight_id);
515+
516+
int virtio_gpu_cmd_backlight_query(struct virtio_gpu_device *vgdev,
517+
uint32_t backlight_id);
518+
493519
/* virtgpu_display.c */
494520
int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev);
495521
void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev);

drivers/gpu/drm/virtio/virtgpu_kms.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,65 @@ int virtio_gpu_find_vqs(struct virtio_gpu_device *vgdev)
173173
return ret;
174174
}
175175

176+
static int virtio_backlight_device_update_status(struct backlight_device *bd)
177+
{
178+
int ret = 0;
179+
struct virtio_gpu_backlight *backlight = bl_get_data(bd);
180+
backlight->power = bd->props.power;
181+
backlight->brightness = bd->props.brightness;
182+
ret = virtio_gpu_cmd_backlight_update_status(backlight->vgdev, backlight->backlight_id);
183+
return ret;
184+
}
185+
186+
static int virtio_backlight_device_get_brightness(struct backlight_device *bd)
187+
{
188+
int ret = 0;
189+
struct virtio_gpu_backlight *backlight = bl_get_data(bd);
190+
ret = virtio_gpu_cmd_get_brightness(backlight->vgdev, backlight->backlight_id);
191+
return backlight->brightness;
192+
}
193+
194+
static const struct backlight_ops virtio_backlight_device_ops = {
195+
.update_status = virtio_backlight_device_update_status,
196+
.get_brightness = virtio_backlight_device_get_brightness,
197+
};
198+
199+
int virtio_backlight_device_register(struct virtio_gpu_device *vgdev, int index)
200+
{
201+
struct backlight_properties props;
202+
char *name;
203+
struct backlight_device *bd;
204+
int ret = 0;
205+
memset(&props, 0, sizeof(props));
206+
if (index >= vgdev->num_backlight) {
207+
return -EINVAL;
208+
}
209+
vgdev->backlight[index].vgdev = vgdev;
210+
ret = virtio_gpu_cmd_backlight_query(vgdev, index);
211+
if (ret) {
212+
pr_err("fail to query backlight(%d) device config, ret:%d", index, ret);
213+
return ret;
214+
}
215+
216+
props.type = vgdev->backlight[index].type;
217+
props.power = vgdev->backlight[index].power;
218+
props.scale = vgdev->backlight[index].scale;
219+
props.brightness = vgdev->backlight[index].brightness;
220+
props.max_brightness = vgdev->backlight[index].max_brightness;
221+
name = kasprintf(GFP_KERNEL, "virtio-gpu-backlight%d", index);
222+
bd = devm_backlight_device_register(&vgdev->vdev->dev, name, &vgdev->vdev->dev,
223+
&vgdev->backlight[index], &virtio_backlight_device_ops, &props);
224+
if (IS_ERR(bd)) {
225+
DRM_ERROR("failed to register backlight device\n");
226+
kfree(name);
227+
return PTR_ERR(bd);
228+
}
229+
vgdev->backlight[index].bd = bd;
230+
DRM_INFO("backlight device:%s registered\n", name);
231+
kfree(name);
232+
return 0;
233+
}
234+
176235
int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
177236
{
178237
struct virtio_gpu_device *vgdev;
@@ -253,6 +312,10 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
253312
vgdev->has_modifier = true;
254313
}
255314
}
315+
if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_BACKLIGHT)) {
316+
vgdev->has_backlight = true;
317+
}
318+
256319
if (virtio_get_shm_region(vgdev->vdev, &vgdev->host_visible_region,
257320
VIRTIO_GPU_SHM_ID_HOST_VISIBLE)) {
258321
if (!devm_request_mem_region(&vgdev->vdev->dev,
@@ -333,8 +396,21 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
333396
goto err_vbufs;
334397
}
335398

399+
vgdev->num_backlight = 0;
400+
if (vgdev->has_backlight) {
401+
virtio_cread_le(vgdev->vdev, struct virtio_gpu_config,
402+
num_backlight, &vgdev->num_backlight);
403+
if (vgdev->num_backlight > MAX_BACKLIGHT_NUM)
404+
vgdev->num_backlight = MAX_BACKLIGHT_NUM;
405+
}
406+
DRM_INFO("number of virtio backlight: %d\n", vgdev->num_backlight);
407+
336408
virtio_device_ready(vgdev->vdev);
337409

410+
for(i = 0; i < vgdev->num_backlight; i++) {
411+
virtio_backlight_device_register(vgdev, i);
412+
}
413+
338414
if (num_capsets)
339415
virtio_gpu_get_capsets(vgdev, num_capsets);
340416

drivers/gpu/drm/virtio/virtgpu_vq.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,3 +1583,132 @@ void virtio_gpu_cmd_set_scaling(struct virtio_gpu_device *vgdev,
15831583

15841584
virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
15851585
}
1586+
1587+
int virtio_gpu_cmd_backlight_update_status(struct virtio_gpu_device *vgdev,
1588+
uint32_t backlight_id)
1589+
{
1590+
struct virtio_gpu_backlight_update_status *cmd_p;
1591+
struct virtio_gpu_vbuffer *vbuf;
1592+
1593+
if (backlight_id >= vgdev->num_backlight) {
1594+
return -EINVAL;
1595+
}
1596+
cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
1597+
memset(cmd_p, 0, sizeof(*cmd_p));
1598+
cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_BACKLIGHT_UPDATE_STATUS);
1599+
cmd_p->backlight_id = cpu_to_le32(backlight_id);
1600+
cmd_p->brightness = cpu_to_le32(vgdev->backlight[backlight_id].brightness);
1601+
cmd_p->power = cpu_to_le32(vgdev->backlight[backlight_id].power);
1602+
1603+
virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
1604+
virtio_gpu_notify(vgdev);
1605+
return 0;
1606+
}
1607+
1608+
static void virtio_gpu_cmd_get_backlightness_cb(struct virtio_gpu_device *vgdev,
1609+
struct virtio_gpu_vbuffer *vbuf)
1610+
{
1611+
struct virtio_gpu_get_brightness *cmd_p =
1612+
(struct virtio_gpu_get_brightness *)vbuf->buf;
1613+
struct virtio_gpu_resp_brightness *resp =
1614+
(struct virtio_gpu_resp_brightness *)vbuf->resp_buf;
1615+
int32_t brightness = le32_to_cpu(resp->brightness);
1616+
uint32_t backlight_id = cmd_p->backlight_id;
1617+
if (backlight_id < vgdev->num_backlight) {
1618+
vgdev->backlight[backlight_id].brightness = brightness;
1619+
}
1620+
complete(&vbuf->notify);
1621+
}
1622+
1623+
int virtio_gpu_cmd_get_brightness(struct virtio_gpu_device *vgdev,
1624+
uint32_t backlight_id)
1625+
{
1626+
struct virtio_gpu_get_brightness *cmd_p;
1627+
struct virtio_gpu_vbuffer *vbuf;
1628+
void *resp_buf;
1629+
int ret = 0;
1630+
1631+
if (backlight_id >= vgdev->num_backlight)
1632+
return -EINVAL;
1633+
resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_brightness),
1634+
GFP_KERNEL);
1635+
if (!resp_buf)
1636+
return -ENOMEM;
1637+
1638+
cmd_p = virtio_gpu_alloc_cmd_resp
1639+
(vgdev, &virtio_gpu_cmd_get_backlightness_cb, &vbuf,
1640+
sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_brightness),
1641+
resp_buf);
1642+
memset(cmd_p, 0, sizeof(*cmd_p));
1643+
1644+
init_completion(&vbuf->notify);
1645+
cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_BACKLIGHT_GET);
1646+
cmd_p->backlight_id = backlight_id;
1647+
virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
1648+
virtio_gpu_notify(vgdev);
1649+
ret = wait_for_completion_interruptible_timeout(&vbuf->notify, 100*HZ);
1650+
if (ret <= 0)
1651+
return -ETIME;
1652+
return 0;
1653+
}
1654+
1655+
static void virtio_gpu_cmd_get_backlight_info_cb(struct virtio_gpu_device *vgdev,
1656+
struct virtio_gpu_vbuffer *vbuf)
1657+
{
1658+
struct virtio_gpu_get_backlight_info *cmd_p =
1659+
(struct virtio_gpu_get_backlight_info *)vbuf->buf;
1660+
struct virtio_gpu_resp_backlight_info *resp =
1661+
(struct virtio_gpu_resp_backlight_info *)vbuf->resp_buf;
1662+
int32_t brightness = le32_to_cpu(resp->brightness);
1663+
int32_t max_brightness = le32_to_cpu(resp->max_brightness);
1664+
int32_t power = le32_to_cpu(resp->power);
1665+
int32_t type = le32_to_cpu(resp->type);
1666+
int32_t scale = le32_to_cpu(resp->scale);
1667+
uint32_t backlight_id = cmd_p->backlight_id;
1668+
if (backlight_id < vgdev->num_backlight) {
1669+
vgdev->backlight[backlight_id].brightness = brightness;
1670+
vgdev->backlight[backlight_id].max_brightness = max_brightness;
1671+
vgdev->backlight[backlight_id].power = power;
1672+
if (type > 0 && type < BACKLIGHT_TYPE_MAX)
1673+
vgdev->backlight[backlight_id].type = type;
1674+
else
1675+
vgdev->backlight[backlight_id].type = BACKLIGHT_RAW;
1676+
if (scale >= BACKLIGHT_SCALE_UNKNOWN && scale <= BACKLIGHT_SCALE_NON_LINEAR)
1677+
vgdev->backlight[backlight_id].scale = scale;
1678+
else
1679+
vgdev->backlight[backlight_id].scale = BACKLIGHT_SCALE_UNKNOWN;
1680+
}
1681+
complete(&vbuf->notify);
1682+
}
1683+
1684+
int virtio_gpu_cmd_backlight_query(struct virtio_gpu_device *vgdev,
1685+
uint32_t backlight_id)
1686+
{
1687+
struct virtio_gpu_get_backlight_info *cmd_p;
1688+
struct virtio_gpu_vbuffer *vbuf;
1689+
void *resp_buf;
1690+
int ret = 0;
1691+
1692+
if (backlight_id >= vgdev->num_backlight)
1693+
return -EINVAL;
1694+
resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_backlight_info),
1695+
GFP_KERNEL);
1696+
if (!resp_buf)
1697+
return -ENOMEM;
1698+
1699+
cmd_p = virtio_gpu_alloc_cmd_resp
1700+
(vgdev, &virtio_gpu_cmd_get_backlight_info_cb, &vbuf,
1701+
sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_backlight_info),
1702+
resp_buf);
1703+
init_completion(&vbuf->notify);
1704+
memset(cmd_p, 0, sizeof(*cmd_p));
1705+
1706+
cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_BACKLIGHT_QUERY);
1707+
cmd_p->backlight_id = backlight_id;
1708+
virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
1709+
virtio_gpu_notify(vgdev);
1710+
ret = wait_for_completion_interruptible_timeout(&vbuf->notify, 100*HZ);
1711+
if (ret <= 0)
1712+
return -ETIME;
1713+
return 0;
1714+
}

include/uapi/linux/virtio_gpu.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575

7676
#define VIRTIO_GPU_F_VBLANK 7
7777

78+
#define VIRTIO_GPU_F_BACKLIGHT 8
79+
7880
#define VIRTIO_GPU_F_ALLOW_P2P 13
7981

8082
/*
@@ -141,6 +143,11 @@ enum virtio_gpu_ctrl_type {
141143
VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
142144
VIRTIO_GPU_CMD_MOVE_CURSOR,
143145

146+
/* backlight cmd */
147+
VIRTIO_GPU_CMD_BACKLIGHT_UPDATE_STATUS = 0x0400,
148+
VIRTIO_GPU_CMD_BACKLIGHT_GET,
149+
VIRTIO_GPU_CMD_BACKLIGHT_QUERY,
150+
144151
/* success responses */
145152
VIRTIO_GPU_RESP_OK_NODATA = 0x1100,
146153
VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
@@ -149,6 +156,8 @@ enum virtio_gpu_ctrl_type {
149156
VIRTIO_GPU_RESP_OK_EDID,
150157
VIRTIO_GPU_RESP_OK_RESOURCE_UUID,
151158
VIRTIO_GPU_RESP_OK_MAP_INFO,
159+
VIRTIO_GPU_RESP_OK_BACKLIGHT_GET,
160+
VIRTIO_GPU_RESP_OK_BACKLIGHT,
152161

153162
/* error responses */
154163
VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
@@ -300,6 +309,45 @@ struct virtio_gpu_set_scaling {
300309
__le32 padding;
301310
};
302311

312+
/* VIRTIO_GPU_CMD_BACKLIGHT_UPDATE_STATUS */
313+
struct virtio_gpu_backlight_update_status {
314+
struct virtio_gpu_ctrl_hdr hdr;
315+
__le32 backlight_id;
316+
__le32 brightness;
317+
__le32 power;
318+
__le32 padding;
319+
};
320+
321+
/* VIRTIO_GPU_CMD_BACKLIGHT_GET */
322+
struct virtio_gpu_get_brightness {
323+
struct virtio_gpu_ctrl_hdr hdr;
324+
__le32 backlight_id;
325+
__le32 padding;
326+
};
327+
328+
struct virtio_gpu_resp_brightness {
329+
struct virtio_gpu_ctrl_hdr hdr;
330+
__le32 brightness;
331+
__le32 padding;
332+
};
333+
334+
/* VIRTIO_GPU_CMD_BACKLIGHT_QUERY */
335+
struct virtio_gpu_get_backlight_info {
336+
struct virtio_gpu_ctrl_hdr hdr;
337+
__le32 backlight_id;
338+
__le32 padding;
339+
};
340+
341+
struct virtio_gpu_resp_backlight_info {
342+
struct virtio_gpu_ctrl_hdr hdr;
343+
__le32 brightness;
344+
__le32 max_brightness;
345+
__le32 power;
346+
__le32 type;
347+
__le32 scale;
348+
__le32 padding;
349+
};
350+
303351
/* VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: simple transfer to_host */
304352
struct virtio_gpu_transfer_to_host_2d {
305353
struct virtio_gpu_ctrl_hdr hdr;
@@ -487,6 +535,7 @@ struct virtio_gpu_config {
487535
__le32 num_scanouts;
488536
__le32 num_capsets;
489537
__le32 num_pipe;
538+
__le32 num_backlight;
490539
};
491540

492541
/* simple formats for fbcon/X use */

0 commit comments

Comments
 (0)