1// SPDX-License-Identifier: GPL-2.0-only OR MIT 2/* Copyright The Asahi Linux Contributors */ 3 4#include <drm/drm_modes.h> 5#include <drm/drm_rect.h> 6 7#include "dcp-internal.h" 8 9struct apple_dcp; 10 11typedef void (*dcp_callback_t)(struct apple_dcp *, void *, void *); 12 13 14#define DCP_THUNK_VOID(func, handle) \ 15 static void func(struct apple_dcp *dcp, bool oob, dcp_callback_t cb, \ 16 void *cookie) \ 17 { \ 18 dcp_push(dcp, oob, &dcp_methods[handle], 0, 0, NULL, cb, cookie); \ 19 } 20 21#define DCP_THUNK_OUT(func, handle, T) \ 22 static void func(struct apple_dcp *dcp, bool oob, dcp_callback_t cb, \ 23 void *cookie) \ 24 { \ 25 dcp_push(dcp, oob, &dcp_methods[handle], 0, sizeof(T), NULL, cb, cookie); \ 26 } 27 28#define DCP_THUNK_IN(func, handle, T) \ 29 static void func(struct apple_dcp *dcp, bool oob, T *data, \ 30 dcp_callback_t cb, void *cookie) \ 31 { \ 32 dcp_push(dcp, oob, &dcp_methods[handle], sizeof(T), 0, data, cb, cookie); \ 33 } 34 35#define DCP_THUNK_INOUT(func, handle, T_in, T_out) \ 36 static void func(struct apple_dcp *dcp, bool oob, T_in *data, \ 37 dcp_callback_t cb, void *cookie) \ 38 { \ 39 dcp_push(dcp, oob, &dcp_methods[handle], sizeof(T_in), sizeof(T_out), data, \ 40 cb, cookie); \ 41 } 42 43#define IOMFB_THUNK_INOUT(name) \ 44 static void iomfb_ ## name(struct apple_dcp *dcp, bool oob, \ 45 struct iomfb_ ## name ## _req *data, \ 46 dcp_callback_t cb, void *cookie) \ 47 { \ 48 dcp_push(dcp, oob, &dcp_methods[iomfbep_ ## name], \ 49 sizeof(struct iomfb_ ## name ## _req), \ 50 sizeof(struct iomfb_ ## name ## _resp), \ 51 data, cb, cookie); \ 52 } 53 54/* 55 * Define type-safe trampolines. Define typedefs to enforce type-safety on the 56 * input data (so if the types don't match, gcc errors out). 57 */ 58 59#define TRAMPOLINE_VOID(func, handler) \ 60 static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 61 { \ 62 trace_iomfb_callback(dcp, tag, #handler); \ 63 handler(dcp); \ 64 return true; \ 65 } 66 67#define TRAMPOLINE_IN(func, handler, T_in) \ 68 typedef void (*callback_##handler)(struct apple_dcp *, T_in *); \ 69 \ 70 static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 71 { \ 72 callback_##handler cb = handler; \ 73 \ 74 trace_iomfb_callback(dcp, tag, #handler); \ 75 cb(dcp, in); \ 76 return true; \ 77 } 78 79#define TRAMPOLINE_INOUT(func, handler, T_in, T_out) \ 80 typedef T_out (*callback_##handler)(struct apple_dcp *, T_in *); \ 81 \ 82 static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 83 { \ 84 T_out *typed_out = out; \ 85 callback_##handler cb = handler; \ 86 \ 87 trace_iomfb_callback(dcp, tag, #handler); \ 88 *typed_out = cb(dcp, in); \ 89 return true; \ 90 } 91 92#define TRAMPOLINE_OUT(func, handler, T_out) \ 93 static bool __maybe_unused func(struct apple_dcp *dcp, int tag, void *out, void *in) \ 94 { \ 95 T_out *typed_out = out; \ 96 \ 97 trace_iomfb_callback(dcp, tag, #handler); \ 98 *typed_out = handler(dcp); \ 99 return true; \ 100 } 101 102/* Call a DCP function given by a tag */ 103void dcp_push(struct apple_dcp *dcp, bool oob, const struct dcp_method_entry *call, 104 u32 in_len, u32 out_len, void *data, dcp_callback_t cb, 105 void *cookie); 106 107/* Parse a callback tag "D123" into the ID 123. Returns -EINVAL on failure. */ 108int dcp_parse_tag(char tag[4]); 109 110void dcp_ack(struct apple_dcp *dcp, enum dcp_context_id context); 111 112/* 113 * DRM specifies rectangles as start and end coordinates. DCP specifies 114 * rectangles as a start coordinate and a width/height. Convert a DRM rectangle 115 * to a DCP rectangle. 116 */ 117struct dcp_rect drm_to_dcp_rect(struct drm_rect *rect); 118 119u32 drm_format_to_dcp(u32 drm); 120 121/* The user may own drm_display_mode, so we need to search for our copy */ 122struct dcp_display_mode *lookup_mode(struct apple_dcp *dcp, 123 const struct drm_display_mode *mode); 124