| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | On Screen Display cx23415 Framebuffer driver |
|---|
| 3 | 4 | |
|---|
| .. | .. |
|---|
| 23 | 24 | |
|---|
| 24 | 25 | Copyright (C) 2006 Ian Armstrong <ian@iarmst.demon.co.uk> |
|---|
| 25 | 26 | |
|---|
| 26 | | - This program is free software; you can redistribute it and/or modify |
|---|
| 27 | | - it under the terms of the GNU General Public License as published by |
|---|
| 28 | | - the Free Software Foundation; either version 2 of the License, or |
|---|
| 29 | | - (at your option) any later version. |
|---|
| 30 | | - |
|---|
| 31 | | - This program is distributed in the hope that it will be useful, |
|---|
| 32 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 33 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 34 | | - GNU General Public License for more details. |
|---|
| 35 | | - |
|---|
| 36 | | - You should have received a copy of the GNU General Public License |
|---|
| 37 | | - along with this program; if not, write to the Free Software |
|---|
| 38 | | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 39 | 27 | */ |
|---|
| 40 | 28 | |
|---|
| 41 | 29 | #include "ivtv-driver.h" |
|---|
| .. | .. |
|---|
| 49 | 37 | #include <linux/ivtvfb.h> |
|---|
| 50 | 38 | |
|---|
| 51 | 39 | #ifdef CONFIG_X86_64 |
|---|
| 52 | | -#include <asm/pat.h> |
|---|
| 40 | +#include <asm/memtype.h> |
|---|
| 53 | 41 | #endif |
|---|
| 54 | 42 | |
|---|
| 55 | 43 | /* card parameters */ |
|---|
| 56 | 44 | static int ivtvfb_card_id = -1; |
|---|
| 57 | 45 | static int ivtvfb_debug = 0; |
|---|
| 46 | +static bool ivtvfb_force_pat = IS_ENABLED(CONFIG_VIDEO_FB_IVTV_FORCE_PAT); |
|---|
| 58 | 47 | static bool osd_laced; |
|---|
| 59 | 48 | static int osd_depth; |
|---|
| 60 | 49 | static int osd_upper; |
|---|
| .. | .. |
|---|
| 64 | 53 | |
|---|
| 65 | 54 | module_param(ivtvfb_card_id, int, 0444); |
|---|
| 66 | 55 | module_param_named(debug,ivtvfb_debug, int, 0644); |
|---|
| 56 | +module_param_named(force_pat, ivtvfb_force_pat, bool, 0644); |
|---|
| 67 | 57 | module_param(osd_laced, bool, 0444); |
|---|
| 68 | 58 | module_param(osd_depth, int, 0444); |
|---|
| 69 | 59 | module_param(osd_upper, int, 0444); |
|---|
| .. | .. |
|---|
| 78 | 68 | MODULE_PARM_DESC(debug, |
|---|
| 79 | 69 | "Debug level (bitmask). Default: errors only\n" |
|---|
| 80 | 70 | "\t\t\t(debug = 3 gives full debugging)"); |
|---|
| 71 | + |
|---|
| 72 | +MODULE_PARM_DESC(force_pat, |
|---|
| 73 | + "Force initialization on x86 PAT-enabled systems (bool).\n"); |
|---|
| 81 | 74 | |
|---|
| 82 | 75 | /* Why upper, left, xres, yres, depth, laced ? To match terminology used |
|---|
| 83 | 76 | by fbset. |
|---|
| .. | .. |
|---|
| 288 | 281 | /* Map User DMA */ |
|---|
| 289 | 282 | if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) { |
|---|
| 290 | 283 | mutex_unlock(&itv->udma.lock); |
|---|
| 291 | | - IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with get_user_pages: %d bytes, %d pages returned\n", |
|---|
| 284 | + IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with pin_user_pages: %d bytes, %d pages returned\n", |
|---|
| 292 | 285 | size_in_bytes, itv->udma.page_count); |
|---|
| 293 | 286 | |
|---|
| 294 | | - /* get_user_pages must have failed completely */ |
|---|
| 287 | + /* pin_user_pages must have failed completely */ |
|---|
| 295 | 288 | return -EIO; |
|---|
| 296 | 289 | } |
|---|
| 297 | 290 | |
|---|
| .. | .. |
|---|
| 356 | 349 | IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count); |
|---|
| 357 | 350 | |
|---|
| 358 | 351 | /* Check Source */ |
|---|
| 359 | | - if (!access_ok(VERIFY_READ, source + dest_offset, count)) { |
|---|
| 352 | + if (!access_ok(source + dest_offset, count)) { |
|---|
| 360 | 353 | IVTVFB_WARN("Invalid userspace pointer %p\n", source); |
|---|
| 361 | 354 | |
|---|
| 362 | 355 | IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source %p count %d\n", |
|---|
| .. | .. |
|---|
| 624 | 617 | |
|---|
| 625 | 618 | IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n"); |
|---|
| 626 | 619 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
|---|
| 627 | | - strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id)); |
|---|
| 620 | + strscpy(fix->id, "cx23415 TV out", sizeof(fix->id)); |
|---|
| 628 | 621 | fix->smem_start = oi->video_pbase; |
|---|
| 629 | 622 | fix->smem_len = oi->video_buffer_size; |
|---|
| 630 | 623 | fix->type = FB_TYPE_PACKED_PIXELS; |
|---|
| .. | .. |
|---|
| 932 | 925 | return 0; |
|---|
| 933 | 926 | } |
|---|
| 934 | 927 | |
|---|
| 935 | | -static struct fb_ops ivtvfb_ops = { |
|---|
| 928 | +static const struct fb_ops ivtvfb_ops = { |
|---|
| 936 | 929 | .owner = THIS_MODULE, |
|---|
| 937 | 930 | .fb_write = ivtvfb_write, |
|---|
| 938 | 931 | .fb_check_var = ivtvfb_check_var, |
|---|
| .. | .. |
|---|
| 1056 | 1049 | |
|---|
| 1057 | 1050 | oi->ivtvfb_info.node = -1; |
|---|
| 1058 | 1051 | oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT; |
|---|
| 1059 | | - oi->ivtvfb_info.fbops = &ivtvfb_ops; |
|---|
| 1060 | 1052 | oi->ivtvfb_info.par = itv; |
|---|
| 1061 | 1053 | oi->ivtvfb_info.var = oi->ivtvfb_defined; |
|---|
| 1062 | 1054 | oi->ivtvfb_info.fix = oi->ivtvfb_fix; |
|---|
| .. | .. |
|---|
| 1167 | 1159 | |
|---|
| 1168 | 1160 | #ifdef CONFIG_X86_64 |
|---|
| 1169 | 1161 | if (pat_enabled()) { |
|---|
| 1170 | | - pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n"); |
|---|
| 1171 | | - return -ENODEV; |
|---|
| 1162 | + if (ivtvfb_force_pat) { |
|---|
| 1163 | + pr_info("PAT is enabled. Write-combined framebuffer caching will be disabled.\n"); |
|---|
| 1164 | + pr_info("To enable caching, boot with nopat kernel parameter\n"); |
|---|
| 1165 | + } else { |
|---|
| 1166 | + pr_warn("ivtvfb needs PAT disabled for write-combined framebuffer caching.\n"); |
|---|
| 1167 | + pr_warn("Boot with nopat kernel parameter to use caching, or use the\n"); |
|---|
| 1168 | + pr_warn("force_pat module parameter to run with caching disabled\n"); |
|---|
| 1169 | + return -ENODEV; |
|---|
| 1170 | + } |
|---|
| 1172 | 1171 | } |
|---|
| 1173 | 1172 | #endif |
|---|
| 1174 | 1173 | |
|---|
| .. | .. |
|---|
| 1220 | 1219 | |
|---|
| 1221 | 1220 | /* Allocate DMA */ |
|---|
| 1222 | 1221 | ivtv_udma_alloc(itv); |
|---|
| 1222 | + itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps |= |
|---|
| 1223 | + V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
|---|
| 1224 | + itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps |= |
|---|
| 1225 | + V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
|---|
| 1226 | + itv->v4l2_cap |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
|---|
| 1223 | 1227 | return 0; |
|---|
| 1224 | 1228 | |
|---|
| 1225 | 1229 | } |
|---|
| .. | .. |
|---|
| 1246 | 1250 | struct osd_info *oi = itv->osd_info; |
|---|
| 1247 | 1251 | |
|---|
| 1248 | 1252 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
|---|
| 1249 | | - if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { |
|---|
| 1250 | | - IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", |
|---|
| 1251 | | - itv->instance); |
|---|
| 1252 | | - return 0; |
|---|
| 1253 | | - } |
|---|
| 1253 | + itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps &= |
|---|
| 1254 | + ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
|---|
| 1255 | + itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps &= |
|---|
| 1256 | + ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
|---|
| 1257 | + itv->v4l2_cap &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
|---|
| 1258 | + unregister_framebuffer(&itv->osd_info->ivtvfb_info); |
|---|
| 1254 | 1259 | IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); |
|---|
| 1255 | 1260 | itv->ivtvfb_restore = NULL; |
|---|
| 1256 | 1261 | ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); |
|---|