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 */
285 /* Send message to Hyper-V host */
292 msg->pipe_hdr.type = PIPE_MSG_DATA; in synthvid_send()
293 msg->pipe_hdr.size = msg->vid_hdr.size; in synthvid_send()
295 ret = vmbus_sendpacket(hdev->channel, msg, in synthvid_send()
296 msg->vid_hdr.size + sizeof(struct pipe_msg_hdr), in synthvid_send()
314 return -ENODEV; in synthvid_send_situ()
325 msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel; in synthvid_send_situ()
326 msg.situ.video_output[0].width_pixels = info->var.xres; in synthvid_send_situ()
327 msg.situ.video_output[0].height_pixels = info->var.yres; in synthvid_send_situ()
328 msg.situ.video_output[0].pitch_bytes = info->fix.line_length; in synthvid_send_situ()
373 struct hv_device *hdev = device_to_hv_device(info->device); in synthvid_update()
378 x2 = info->var.xres; in synthvid_update()
380 y2 = info->var.yres; in synthvid_update()
390 (x2 < x1 || x2 > info->var.xres) ? info->var.xres : x2; in synthvid_update()
392 (y2 < y1 || y2 > info->var.yres) ? info->var.yres : y2; in synthvid_update()
403 if (!par || !par->mmio_vp || !par->dio_vp || !par->fb_ready || in hvfb_docopy()
408 size = dio_fb_size - offset; in hvfb_docopy()
410 memcpy(par->mmio_vp + offset, par->dio_vp + offset, size); in hvfb_docopy()
416 struct hvfb_par *par = p->par; in synthvid_deferred_io()
431 start = pageref->offset; in synthvid_deferred_io()
432 end = start + PAGE_SIZE - 1; in synthvid_deferred_io()
433 y1 = start / p->fix.line_length; in synthvid_deferred_io()
434 y2 = end / p->fix.line_length; in synthvid_deferred_io()
439 if (par->fb_ready && par->need_docopy) in synthvid_deferred_io()
443 if (par->fb_ready && par->update) in synthvid_deferred_io()
444 synthvid_update(p, 0, miny, p->var.xres, maxy + 1); in synthvid_deferred_io()
466 par = info->par; in synthvid_recv_sub()
467 msg = (struct synthvid_msg *)par->recv_buf; in synthvid_recv_sub()
470 if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE || in synthvid_recv_sub()
471 msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE || in synthvid_recv_sub()
472 msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) { in synthvid_recv_sub()
473 memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE); in synthvid_recv_sub()
474 complete(&par->wait); in synthvid_recv_sub()
479 if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) { in synthvid_recv_sub()
480 if (par->fb_ready) { in synthvid_recv_sub()
485 par->update = msg->feature_chg.is_dirt_needed; in synthvid_recv_sub()
486 if (par->update) in synthvid_recv_sub()
487 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); in synthvid_recv_sub()
505 par = info->par; in synthvid_receive()
506 recv_buf = (struct synthvid_msg *)par->recv_buf; in synthvid_receive()
509 ret = vmbus_recvpacket(hdev->channel, recv_buf, in synthvid_receive()
513 recv_buf->pipe_hdr.type == PIPE_MSG_DATA) in synthvid_receive()
533 struct hvfb_par *par = info->par; in synthvid_negotiate_ver()
534 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; in synthvid_negotiate_ver()
539 msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST; in synthvid_negotiate_ver()
540 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + in synthvid_negotiate_ver()
542 msg->ver_req.version = ver; in synthvid_negotiate_ver()
545 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); in synthvid_negotiate_ver()
548 ret = -ETIMEDOUT; in synthvid_negotiate_ver()
551 if (!msg->ver_resp.is_accepted) { in synthvid_negotiate_ver()
552 ret = -ENODEV; in synthvid_negotiate_ver()
556 par->synthvid_version = ver; in synthvid_negotiate_ver()
568 struct hvfb_par *par = info->par; in synthvid_get_supported_resolution()
569 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; in synthvid_get_supported_resolution()
575 msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST; in synthvid_get_supported_resolution()
576 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + in synthvid_get_supported_resolution()
579 msg->resolution_req.maximum_resolution_count = in synthvid_get_supported_resolution()
583 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); in synthvid_get_supported_resolution()
586 ret = -ETIMEDOUT; in synthvid_get_supported_resolution()
590 if (msg->resolution_resp.resolution_count == 0) { in synthvid_get_supported_resolution()
592 ret = -ENODEV; in synthvid_get_supported_resolution()
596 index = msg->resolution_resp.default_resolution_index; in synthvid_get_supported_resolution()
597 if (index >= msg->resolution_resp.resolution_count) { in synthvid_get_supported_resolution()
599 ret = -ENODEV; in synthvid_get_supported_resolution()
604 msg->resolution_resp.supported_resolution[index].width; in synthvid_get_supported_resolution()
606 msg->resolution_resp.supported_resolution[index].height; in synthvid_get_supported_resolution()
612 /* Connect to VSP (Virtual Service Provider) on host */
616 struct hvfb_par *par = info->par; in synthvid_connect_vsp()
619 ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE, in synthvid_connect_vsp()
649 if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) { in synthvid_connect_vsp()
655 screen_fb_size = hdev->channel->offermsg.offer. in synthvid_connect_vsp()
661 vmbus_close(hdev->channel); in synthvid_connect_vsp()
669 struct hvfb_par *par = info->par; in synthvid_send_config()
670 struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; in synthvid_send_config()
676 msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION; in synthvid_send_config()
677 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + in synthvid_send_config()
679 msg->vram.user_ctx = msg->vram.vram_gpa = par->mmio_pp; in synthvid_send_config()
680 msg->vram.is_vram_gpa_specified = 1; in synthvid_send_config()
683 t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); in synthvid_send_config()
686 ret = -ETIMEDOUT; in synthvid_send_config()
689 if (msg->vram_ack.user_ctx != par->mmio_pp) { in synthvid_send_config()
691 ret = -ENODEV; in synthvid_send_config()
712 struct fb_info *info = par->info; in hvfb_update_work()
717 spin_lock_irqsave(&par->delayed_refresh_lock, flags); in hvfb_update_work()
719 par->delayed_refresh = false; in hvfb_update_work()
722 x1 = par->x1; in hvfb_update_work()
723 x2 = par->x2; in hvfb_update_work()
724 y1 = par->y1; in hvfb_update_work()
725 y2 = par->y2; in hvfb_update_work()
728 par->x1 = par->y1 = INT_MAX; in hvfb_update_work()
729 par->x2 = par->y2 = 0; in hvfb_update_work()
731 spin_unlock_irqrestore(&par->delayed_refresh_lock, flags); in hvfb_update_work()
733 if (x1 > info->var.xres || x2 > info->var.xres || in hvfb_update_work()
734 y1 > info->var.yres || y2 > info->var.yres || x2 <= x1) in hvfb_update_work()
738 if (par->need_docopy) in hvfb_update_work()
741 j * info->fix.line_length + in hvfb_update_work()
743 (x2 - x1) * screen_depth / 8); in hvfb_update_work()
746 if (par->fb_ready && par->update) in hvfb_update_work()
751 * Control the on-demand refresh frequency. It schedules a delayed
761 spin_lock_irqsave(&par->delayed_refresh_lock, flags); in hvfb_ondemand_refresh_throttle()
764 par->x1 = min_t(int, par->x1, x1); in hvfb_ondemand_refresh_throttle()
765 par->y1 = min_t(int, par->y1, y1); in hvfb_ondemand_refresh_throttle()
766 par->x2 = max_t(int, par->x2, x2); in hvfb_ondemand_refresh_throttle()
767 par->y2 = max_t(int, par->y2, y2); in hvfb_ondemand_refresh_throttle()
770 if (par->delayed_refresh == false) { in hvfb_ondemand_refresh_throttle()
771 schedule_delayed_work(&par->dwork, in hvfb_ondemand_refresh_throttle()
773 par->delayed_refresh = true; in hvfb_ondemand_refresh_throttle()
776 spin_unlock_irqrestore(&par->delayed_refresh_lock, flags); in hvfb_ondemand_refresh_throttle()
787 info = par->info; in hvfb_on_panic()
788 hdev = device_to_hv_device(info->device); in hvfb_on_panic()
790 if (hv_ringbuffer_spinlock_busy(hdev->channel)) in hvfb_on_panic()
793 par->synchronous_fb = true; in hvfb_on_panic()
794 if (par->need_docopy) in hvfb_on_panic()
805 if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN || in hvfb_check_var()
806 var->xres > screen_width || var->yres > screen_height || in hvfb_check_var()
807 var->bits_per_pixel != screen_depth) in hvfb_check_var()
808 return -EINVAL; in hvfb_check_var()
810 var->xres_virtual = var->xres; in hvfb_check_var()
811 var->yres_virtual = var->yres; in hvfb_check_var()
818 struct hv_device *hdev = device_to_hv_device(info->device); in hvfb_set_par()
826 return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; in chan_to_field()
832 u32 *pal = info->pseudo_palette; in hvfb_setcolreg()
835 return -EINVAL; in hvfb_setcolreg()
837 pal[regno] = chan_to_field(red, &info->var.red) in hvfb_setcolreg()
838 | chan_to_field(green, &info->var.green) in hvfb_setcolreg()
839 | chan_to_field(blue, &info->var.blue) in hvfb_setcolreg()
840 | chan_to_field(transp, &info->var.transp); in hvfb_setcolreg()
857 struct hvfb_par *par = info->par; in hvfb_ops_damage_area()
859 if (par->synchronous_fb) in hvfb_ops_damage_area()
866 * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the
885 struct hvfb_par *par = info->par; in hvfb_get_option()
900 (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) && in hvfb_get_option()
902 (par->synthvid_version == SYNTHVID_VERSION_WIN8 && in hvfb_get_option()
915 * Return physical address if succeeded or -1 if failed.
927 return -1; in hvfb_get_phymem()
933 return -1; in hvfb_get_phymem()
938 hdev->device.coherent_dma_mask = DMA_BIT_MASK(64); in hvfb_get_phymem()
940 vmem = dma_alloc_coherent(&hdev->device, in hvfb_get_phymem()
946 return -1; in hvfb_get_phymem()
963 dma_free_coherent(&hdev->device, in hvfb_release_phymem()
970 /* Get framebuffer memory from Hyper-V video pci space */
973 struct hvfb_par *par = info->par; in hvfb_getmem()
986 pr_err("Unable to find PCI Hyper-V video\n"); in hvfb_getmem()
987 return -ENODEV; in hvfb_getmem()
1000 if (paddr != (phys_addr_t) -1) { in hvfb_getmem()
1001 par->mmio_pp = paddr; in hvfb_getmem()
1002 par->mmio_vp = par->dio_vp = __va(paddr); in hvfb_getmem()
1004 info->fix.smem_start = paddr; in hvfb_getmem()
1005 info->fix.smem_len = screen_fb_size; in hvfb_getmem()
1006 info->screen_base = par->mmio_vp; in hvfb_getmem()
1007 info->screen_size = screen_fb_size; in hvfb_getmem()
1009 par->need_docopy = false; in hvfb_getmem()
1022 ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1, in hvfb_getmem()
1034 fb_virt = ioremap_cache(par->mem->start, screen_fb_size); in hvfb_getmem()
1039 par->dio_vp = vzalloc(round_up(dio_fb_size, PAGE_SIZE)); in hvfb_getmem()
1040 if (par->dio_vp == NULL) in hvfb_getmem()
1044 par->mmio_pp = par->mem->start; in hvfb_getmem()
1046 par->mmio_vp = (unsigned char *) fb_virt; in hvfb_getmem()
1048 info->fix.smem_start = par->mem->start; in hvfb_getmem()
1049 info->fix.smem_len = dio_fb_size; in hvfb_getmem()
1050 info->screen_base = par->dio_vp; in hvfb_getmem()
1051 info->screen_size = dio_fb_size; in hvfb_getmem()
1067 vmbus_free_mmio(par->mem->start, screen_fb_size); in hvfb_getmem()
1068 par->mem = NULL; in hvfb_getmem()
1073 return -ENOMEM; in hvfb_getmem()
1079 struct hvfb_par *par = info->par; in hvfb_putmem()
1081 if (par->need_docopy) { in hvfb_putmem()
1082 vfree(par->dio_vp); in hvfb_putmem()
1083 iounmap(info->screen_base); in hvfb_putmem()
1084 vmbus_free_mmio(par->mem->start, screen_fb_size); in hvfb_putmem()
1086 hvfb_release_phymem(hdev, info->fix.smem_start, in hvfb_putmem()
1090 par->mem = NULL; in hvfb_putmem()
1101 info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device); in hvfb_probe()
1103 return -ENOMEM; in hvfb_probe()
1105 par = info->par; in hvfb_probe()
1106 par->info = info; in hvfb_probe()
1107 par->fb_ready = false; in hvfb_probe()
1108 par->need_docopy = true; in hvfb_probe()
1109 init_completion(&par->wait); in hvfb_probe()
1110 INIT_DELAYED_WORK(&par->dwork, hvfb_update_work); in hvfb_probe()
1112 par->delayed_refresh = false; in hvfb_probe()
1113 spin_lock_init(&par->delayed_refresh_lock); in hvfb_probe()
1114 par->x1 = par->y1 = INT_MAX; in hvfb_probe()
1115 par->x2 = par->y2 = 0; in hvfb_probe()
1117 /* Connect to VSP */ in hvfb_probe()
1121 pr_err("Unable to connect to VSP\n"); in hvfb_probe()
1136 info->var.xres_virtual = info->var.xres = screen_width; in hvfb_probe()
1137 info->var.yres_virtual = info->var.yres = screen_height; in hvfb_probe()
1138 info->var.bits_per_pixel = screen_depth; in hvfb_probe()
1140 if (info->var.bits_per_pixel == 16) { in hvfb_probe()
1141 info->var.red = (struct fb_bitfield){11, 5, 0}; in hvfb_probe()
1142 info->var.green = (struct fb_bitfield){5, 6, 0}; in hvfb_probe()
1143 info->var.blue = (struct fb_bitfield){0, 5, 0}; in hvfb_probe()
1144 info->var.transp = (struct fb_bitfield){0, 0, 0}; in hvfb_probe()
1146 info->var.red = (struct fb_bitfield){16, 8, 0}; in hvfb_probe()
1147 info->var.green = (struct fb_bitfield){8, 8, 0}; in hvfb_probe()
1148 info->var.blue = (struct fb_bitfield){0, 8, 0}; in hvfb_probe()
1149 info->var.transp = (struct fb_bitfield){24, 8, 0}; in hvfb_probe()
1152 info->var.activate = FB_ACTIVATE_NOW; in hvfb_probe()
1153 info->var.height = -1; in hvfb_probe()
1154 info->var.width = -1; in hvfb_probe()
1155 info->var.vmode = FB_VMODE_NONINTERLACED; in hvfb_probe()
1157 strcpy(info->fix.id, KBUILD_MODNAME); in hvfb_probe()
1158 info->fix.type = FB_TYPE_PACKED_PIXELS; in hvfb_probe()
1159 info->fix.visual = FB_VISUAL_TRUECOLOR; in hvfb_probe()
1160 info->fix.line_length = screen_width * screen_depth / 8; in hvfb_probe()
1161 info->fix.accel = FB_ACCEL_NONE; in hvfb_probe()
1163 info->fbops = &hvfb_ops; in hvfb_probe()
1164 info->pseudo_palette = par->pseudo_palette; in hvfb_probe()
1167 info->fbdefio = &synthvid_defio; in hvfb_probe()
1181 par->fb_ready = true; in hvfb_probe()
1183 par->synchronous_fb = false; in hvfb_probe()
1191 par->hvfb_panic_nb.notifier_call = hvfb_on_panic; in hvfb_probe()
1192 par->hvfb_panic_nb.priority = INT_MIN + 10; in hvfb_probe()
1194 &par->hvfb_panic_nb); in hvfb_probe()
1202 vmbus_close(hdev->channel); in hvfb_probe()
1204 cancel_delayed_work_sync(&par->dwork); in hvfb_probe()
1213 struct hvfb_par *par = info->par; in hvfb_remove()
1216 &par->hvfb_panic_nb); in hvfb_remove()
1218 par->update = false; in hvfb_remove()
1219 par->fb_ready = false; in hvfb_remove()
1224 cancel_delayed_work_sync(&par->dwork); in hvfb_remove()
1226 vmbus_close(hdev->channel); in hvfb_remove()
1236 struct hvfb_par *par = info->par; in hvfb_suspend()
1243 cancel_delayed_work_sync(&par->dwork); in hvfb_suspend()
1244 cancel_delayed_work_sync(&info->deferred_work); in hvfb_suspend()
1246 par->update_saved = par->update; in hvfb_suspend()
1247 par->update = false; in hvfb_suspend()
1248 par->fb_ready = false; in hvfb_suspend()
1250 vmbus_close(hdev->channel); in hvfb_suspend()
1260 struct hvfb_par *par = info->par; in hvfb_resume()
1271 vmbus_close(hdev->channel); in hvfb_resume()
1275 par->fb_ready = true; in hvfb_resume()
1276 par->update = par->update_saved; in hvfb_resume()
1278 schedule_delayed_work(&info->deferred_work, info->fbdefio->delay); in hvfb_resume()
1279 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); in hvfb_resume()
1345 return -ENODEV; in hvfb_drv_init()
1370 MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");