Lines Matching +full:vsp +full:- +full:supply
1 // SPDX-License-Identifier: GPL-2.0-only
10 * Hyper-V Synthetic Video Frame Buffer Driver
12 * This is the driver for the Hyper-V Synthetic Video, which supports
31 * "set-vmvideo" command. For example
32 * set-vmvideo -vmname name -horizontalresolution:1920 \
33 * -verticalresolution:1200 -resolutiontype single
38 * CMA memory allocator. To enable this, supply a kernel parameter to give
62 /* Hyper-V Synthetic Video Protocol definitions and structures */
184 #define CURSOR_COMPLETE (-1)
191 u32 hot_x; /* hotspot relative to upper-left of pointer image */
260 /* If true, the VSC notifies the VSP on every framebuffer change */
287 /* Send message to Hyper-V host */
294 msg->pipe_hdr.type = PIPE_MSG_DATA; in synthvid_send()
295 msg->pipe_hdr.size = msg->vid_hdr.size; in synthvid_send()
297 ret = vmbus_sendpacket(hdev->channel, msg, in synthvid_send()
298 msg->vid_hdr.size + sizeof(struct pipe_msg_hdr), in synthvid_send()
316 return -ENODEV; in synthvid_send_situ()
327 msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel; in synthvid_send_situ()
328 msg.situ.video_output[0].width_pixels = info->var.xres; in synthvid_send_situ()
329 msg.situ.video_output[0].height_pixels = info->var.yres; in synthvid_send_situ()
330 msg.situ.video_output[0].pitch_bytes = info->fix.line_length; in synthvid_send_situ()
375 struct hv_device *hdev = device_to_hv_device(info->device); in synthvid_update()
380 x2 = info->var.xres; in synthvid_update()
382 y2 = info->var.yres; in synthvid_update()
392 (x2 < x1 || x2 > info->var.xres) ? info->var.xres : x2; in synthvid_update()
394 (y2 < y1 || y2 > info->var.yres) ? info->var.yres : y2; in synthvid_update()
405 if (!par || !par->mmio_vp || !par->dio_vp || !par->fb_ready || in hvfb_docopy()
410 size = dio_fb_size - offset; in hvfb_docopy()
412 memcpy(par->mmio_vp + offset, par->dio_vp + offset, size); in hvfb_docopy()
418 struct hvfb_par *par = p->par; in synthvid_deferred_io()
433 start = pageref->offset; in synthvid_deferred_io()
434 end = start + PAGE_SIZE - 1; in synthvid_deferred_io()
435 y1 = start / p->fix.line_length; in synthvid_deferred_io()
436 y2 = end / p->fix.line_length; in synthvid_deferred_io()
441 if (par->fb_ready && par->need_docopy) in synthvid_deferred_io()
445 if (par->fb_ready && par->update) in synthvid_deferred_io()
446 synthvid_update(p, 0, miny, p->var.xres, maxy + 1); in synthvid_deferred_io()
468 par = info->par; in synthvid_recv_sub()
469 msg = (struct synthvid_msg *)par->recv_buf; in synthvid_recv_sub()
472 if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE || in synthvid_recv_sub()
473 msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE || in synthvid_recv_sub()
474 msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) { in synthvid_recv_sub()
475 memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE); in synthvid_recv_sub()
476 complete(&par->wait); in synthvid_recv_sub()
481 if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) { in synthvid_recv_sub()
482 if (par->fb_ready) { in synthvid_recv_sub()
487 par->update = msg->feature_chg.is_dirt_needed; in synthvid_recv_sub()
488 if (par->update) in synthvid_recv_sub()
489 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); in synthvid_recv_sub()
507 par = info->par; in synthvid_receive()
508 recv_buf = (struct synthvid_msg *)par->recv_buf; in synthvid_receive()
511 ret = vmbus_recvpacket(hdev->channel, recv_buf, in synthvid_receive()
515 recv_buf->pipe_hdr.type == PIPE_MSG_DATA) in synthvid_receive()
535 struct hvfb_par *par = info->par; in synthvid_negotiate_ver()
536 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; in synthvid_negotiate_ver()
541 msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST; in synthvid_negotiate_ver()
542 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + in synthvid_negotiate_ver()
544 msg->ver_req.version = ver; in synthvid_negotiate_ver()
547 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); in synthvid_negotiate_ver()
550 ret = -ETIMEDOUT; in synthvid_negotiate_ver()
553 if (!msg->ver_resp.is_accepted) { in synthvid_negotiate_ver()
554 ret = -ENODEV; in synthvid_negotiate_ver()
558 par->synthvid_version = ver; in synthvid_negotiate_ver()
570 struct hvfb_par *par = info->par; in synthvid_get_supported_resolution()
571 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; in synthvid_get_supported_resolution()
577 msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST; in synthvid_get_supported_resolution()
578 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + in synthvid_get_supported_resolution()
581 msg->resolution_req.maximum_resolution_count = in synthvid_get_supported_resolution()
585 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); in synthvid_get_supported_resolution()
588 ret = -ETIMEDOUT; in synthvid_get_supported_resolution()
592 if (msg->resolution_resp.resolution_count == 0) { in synthvid_get_supported_resolution()
594 ret = -ENODEV; in synthvid_get_supported_resolution()
598 index = msg->resolution_resp.default_resolution_index; in synthvid_get_supported_resolution()
599 if (index >= msg->resolution_resp.resolution_count) { in synthvid_get_supported_resolution()
601 ret = -ENODEV; in synthvid_get_supported_resolution()
606 msg->resolution_resp.supported_resolution[index].width; in synthvid_get_supported_resolution()
608 msg->resolution_resp.supported_resolution[index].height; in synthvid_get_supported_resolution()
614 /* Connect to VSP (Virtual Service Provider) on host */
618 struct hvfb_par *par = info->par; in synthvid_connect_vsp()
621 ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE, in synthvid_connect_vsp()
651 if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) { in synthvid_connect_vsp()
657 screen_fb_size = hdev->channel->offermsg.offer. in synthvid_connect_vsp()
663 vmbus_close(hdev->channel); in synthvid_connect_vsp()
671 struct hvfb_par *par = info->par; in synthvid_send_config()
672 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; in synthvid_send_config()
678 msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION; in synthvid_send_config()
679 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + in synthvid_send_config()
681 msg->vram.user_ctx = msg->vram.vram_gpa = par->mmio_pp; in synthvid_send_config()
682 msg->vram.is_vram_gpa_specified = 1; in synthvid_send_config()
685 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); in synthvid_send_config()
688 ret = -ETIMEDOUT; in synthvid_send_config()
691 if (msg->vram_ack.user_ctx != par->mmio_pp) { in synthvid_send_config()
693 ret = -ENODEV; in synthvid_send_config()
714 struct fb_info *info = par->info; in hvfb_update_work()
719 spin_lock_irqsave(&par->delayed_refresh_lock, flags); in hvfb_update_work()
721 par->delayed_refresh = false; in hvfb_update_work()
724 x1 = par->x1; in hvfb_update_work()
725 x2 = par->x2; in hvfb_update_work()
726 y1 = par->y1; in hvfb_update_work()
727 y2 = par->y2; in hvfb_update_work()
730 par->x1 = par->y1 = INT_MAX; in hvfb_update_work()
731 par->x2 = par->y2 = 0; in hvfb_update_work()
733 spin_unlock_irqrestore(&par->delayed_refresh_lock, flags); in hvfb_update_work()
735 if (x1 > info->var.xres || x2 > info->var.xres || in hvfb_update_work()
736 y1 > info->var.yres || y2 > info->var.yres || x2 <= x1) in hvfb_update_work()
740 if (par->need_docopy) in hvfb_update_work()
743 j * info->fix.line_length + in hvfb_update_work()
745 (x2 - x1) * screen_depth / 8); in hvfb_update_work()
748 if (par->fb_ready && par->update) in hvfb_update_work()
753 * Control the on-demand refresh frequency. It schedules a delayed
763 spin_lock_irqsave(&par->delayed_refresh_lock, flags); in hvfb_ondemand_refresh_throttle()
766 par->x1 = min_t(int, par->x1, x1); in hvfb_ondemand_refresh_throttle()
767 par->y1 = min_t(int, par->y1, y1); in hvfb_ondemand_refresh_throttle()
768 par->x2 = max_t(int, par->x2, x2); in hvfb_ondemand_refresh_throttle()
769 par->y2 = max_t(int, par->y2, y2); in hvfb_ondemand_refresh_throttle()
772 if (par->delayed_refresh == false) { in hvfb_ondemand_refresh_throttle()
773 schedule_delayed_work(&par->dwork, in hvfb_ondemand_refresh_throttle()
775 par->delayed_refresh = true; in hvfb_ondemand_refresh_throttle()
778 spin_unlock_irqrestore(&par->delayed_refresh_lock, flags); in hvfb_ondemand_refresh_throttle()
789 info = par->info; in hvfb_on_panic()
790 hdev = device_to_hv_device(info->device); in hvfb_on_panic()
792 if (hv_ringbuffer_spinlock_busy(hdev->channel)) in hvfb_on_panic()
795 par->synchronous_fb = true; in hvfb_on_panic()
796 if (par->need_docopy) in hvfb_on_panic()
807 if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN || in hvfb_check_var()
808 var->xres > screen_width || var->yres > screen_height || in hvfb_check_var()
809 var->bits_per_pixel != screen_depth) in hvfb_check_var()
810 return -EINVAL; in hvfb_check_var()
812 var->xres_virtual = var->xres; in hvfb_check_var()
813 var->yres_virtual = var->yres; in hvfb_check_var()
820 struct hv_device *hdev = device_to_hv_device(info->device); in hvfb_set_par()
828 return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; in chan_to_field()
834 u32 *pal = info->pseudo_palette; in hvfb_setcolreg()
837 return -EINVAL; in hvfb_setcolreg()
839 pal[regno] = chan_to_field(red, &info->var.red) in hvfb_setcolreg()
840 | chan_to_field(green, &info->var.green) in hvfb_setcolreg()
841 | chan_to_field(blue, &info->var.blue) in hvfb_setcolreg()
842 | chan_to_field(transp, &info->var.transp); in hvfb_setcolreg()
859 struct hvfb_par *par = info->par; in hvfb_ops_damage_area()
861 if (par->synchronous_fb) in hvfb_ops_damage_area()
879 * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the
899 struct hvfb_par *par = info->par; in hvfb_get_option()
914 (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) && in hvfb_get_option()
916 (par->synthvid_version == SYNTHVID_VERSION_WIN8 && in hvfb_get_option()
929 * Return physical address if succeeded or -1 if failed.
941 return -1; in hvfb_get_phymem()
947 return -1; in hvfb_get_phymem()
952 hdev->device.coherent_dma_mask = DMA_BIT_MASK(64); in hvfb_get_phymem()
954 vmem = dma_alloc_coherent(&hdev->device, in hvfb_get_phymem()
960 return -1; in hvfb_get_phymem()
984 /* Get framebuffer memory from Hyper-V video pci space */
987 struct hvfb_par *par = info->par; in hvfb_getmem()
1000 pr_err("Unable to find PCI Hyper-V video\n"); in hvfb_getmem()
1001 return -ENODEV; in hvfb_getmem()
1015 if (paddr != (phys_addr_t) -1) { in hvfb_getmem()
1016 par->mmio_pp = paddr; in hvfb_getmem()
1017 par->mmio_vp = par->dio_vp = __va(paddr); in hvfb_getmem()
1019 info->fix.smem_start = paddr; in hvfb_getmem()
1020 info->fix.smem_len = screen_fb_size; in hvfb_getmem()
1021 info->screen_base = par->mmio_vp; in hvfb_getmem()
1022 info->screen_size = screen_fb_size; in hvfb_getmem()
1024 par->need_docopy = false; in hvfb_getmem()
1047 ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1, in hvfb_getmem()
1059 fb_virt = ioremap_cache(par->mem->start, screen_fb_size); in hvfb_getmem()
1064 par->dio_vp = vzalloc(round_up(dio_fb_size, PAGE_SIZE)); in hvfb_getmem()
1065 if (par->dio_vp == NULL) in hvfb_getmem()
1069 par->mmio_pp = par->mem->start; in hvfb_getmem()
1071 par->mmio_vp = (unsigned char *) fb_virt; in hvfb_getmem()
1073 info->fix.smem_start = par->mem->start; in hvfb_getmem()
1074 info->fix.smem_len = dio_fb_size; in hvfb_getmem()
1075 info->screen_base = par->dio_vp; in hvfb_getmem()
1076 info->screen_size = dio_fb_size; in hvfb_getmem()
1087 vmbus_free_mmio(par->mem->start, screen_fb_size); in hvfb_getmem()
1088 par->mem = NULL; in hvfb_getmem()
1093 return -ENOMEM; in hvfb_getmem()
1099 struct hvfb_par *par = info->par; in hvfb_putmem()
1101 if (par->need_docopy) { in hvfb_putmem()
1102 vfree(par->dio_vp); in hvfb_putmem()
1103 iounmap(par->mmio_vp); in hvfb_putmem()
1104 vmbus_free_mmio(par->mem->start, screen_fb_size); in hvfb_putmem()
1106 hvfb_release_phymem(info->device, info->fix.smem_start, in hvfb_putmem()
1110 par->mem = NULL; in hvfb_putmem()
1121 info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device); in hvfb_probe()
1123 return -ENOMEM; in hvfb_probe()
1125 par = info->par; in hvfb_probe()
1126 par->info = info; in hvfb_probe()
1127 par->fb_ready = false; in hvfb_probe()
1128 par->need_docopy = true; in hvfb_probe()
1129 init_completion(&par->wait); in hvfb_probe()
1130 INIT_DELAYED_WORK(&par->dwork, hvfb_update_work); in hvfb_probe()
1132 par->delayed_refresh = false; in hvfb_probe()
1133 spin_lock_init(&par->delayed_refresh_lock); in hvfb_probe()
1134 par->x1 = par->y1 = INT_MAX; in hvfb_probe()
1135 par->x2 = par->y2 = 0; in hvfb_probe()
1137 /* Connect to VSP */ in hvfb_probe()
1141 pr_err("Unable to connect to VSP\n"); in hvfb_probe()
1156 info->var.xres_virtual = info->var.xres = screen_width; in hvfb_probe()
1157 info->var.yres_virtual = info->var.yres = screen_height; in hvfb_probe()
1158 info->var.bits_per_pixel = screen_depth; in hvfb_probe()
1160 if (info->var.bits_per_pixel == 16) { in hvfb_probe()
1161 info->var.red = (struct fb_bitfield){11, 5, 0}; in hvfb_probe()
1162 info->var.green = (struct fb_bitfield){5, 6, 0}; in hvfb_probe()
1163 info->var.blue = (struct fb_bitfield){0, 5, 0}; in hvfb_probe()
1164 info->var.transp = (struct fb_bitfield){0, 0, 0}; in hvfb_probe()
1166 info->var.red = (struct fb_bitfield){16, 8, 0}; in hvfb_probe()
1167 info->var.green = (struct fb_bitfield){8, 8, 0}; in hvfb_probe()
1168 info->var.blue = (struct fb_bitfield){0, 8, 0}; in hvfb_probe()
1169 info->var.transp = (struct fb_bitfield){24, 8, 0}; in hvfb_probe()
1172 info->var.activate = FB_ACTIVATE_NOW; in hvfb_probe()
1173 info->var.height = -1; in hvfb_probe()
1174 info->var.width = -1; in hvfb_probe()
1175 info->var.vmode = FB_VMODE_NONINTERLACED; in hvfb_probe()
1177 strcpy(info->fix.id, KBUILD_MODNAME); in hvfb_probe()
1178 info->fix.type = FB_TYPE_PACKED_PIXELS; in hvfb_probe()
1179 info->fix.visual = FB_VISUAL_TRUECOLOR; in hvfb_probe()
1180 info->fix.line_length = screen_width * screen_depth / 8; in hvfb_probe()
1181 info->fix.accel = FB_ACCEL_NONE; in hvfb_probe()
1183 info->fbops = &hvfb_ops; in hvfb_probe()
1184 info->pseudo_palette = par->pseudo_palette; in hvfb_probe()
1187 info->fbdefio = &synthvid_defio; in hvfb_probe()
1195 ret = devm_register_framebuffer(&hdev->device, info); in hvfb_probe()
1201 par->fb_ready = true; in hvfb_probe()
1203 par->synchronous_fb = false; in hvfb_probe()
1211 par->hvfb_panic_nb.notifier_call = hvfb_on_panic; in hvfb_probe()
1212 par->hvfb_panic_nb.priority = INT_MIN + 10; in hvfb_probe()
1214 &par->hvfb_panic_nb); in hvfb_probe()
1222 vmbus_close(hdev->channel); in hvfb_probe()
1224 cancel_delayed_work_sync(&par->dwork); in hvfb_probe()
1233 struct hvfb_par *par = info->par; in hvfb_remove()
1236 &par->hvfb_panic_nb); in hvfb_remove()
1238 par->update = false; in hvfb_remove()
1239 par->fb_ready = false; in hvfb_remove()
1243 cancel_delayed_work_sync(&par->dwork); in hvfb_remove()
1245 vmbus_close(hdev->channel); in hvfb_remove()
1252 struct hvfb_par *par = info->par; in hvfb_suspend()
1259 cancel_delayed_work_sync(&par->dwork); in hvfb_suspend()
1260 cancel_delayed_work_sync(&info->deferred_work); in hvfb_suspend()
1262 par->update_saved = par->update; in hvfb_suspend()
1263 par->update = false; in hvfb_suspend()
1264 par->fb_ready = false; in hvfb_suspend()
1266 vmbus_close(hdev->channel); in hvfb_suspend()
1276 struct hvfb_par *par = info->par; in hvfb_resume()
1287 vmbus_close(hdev->channel); in hvfb_resume()
1291 par->fb_ready = true; in hvfb_resume()
1292 par->update = par->update_saved; in hvfb_resume()
1294 schedule_delayed_work(&info->deferred_work, info->fbdefio->delay); in hvfb_resume()
1295 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); in hvfb_resume()
1361 return -ENODEV; in hvfb_drv_init()
1386 MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");