.. | .. |
---|
| 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); |
---|