1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved. 4 * Author: James.Qian.Wang <james.qian.wang@arm.com> 5 * 6 */ 7 #include <drm/drm_print.h> 8 9 #include "komeda_dev.h" 10 #include "komeda_pipeline.h" 11 12 /** komeda_pipeline_add - Add a pipeline to &komeda_dev */ 13 struct komeda_pipeline * 14 komeda_pipeline_add(struct komeda_dev *mdev, size_t size, 15 struct komeda_pipeline_funcs *funcs) 16 { 17 struct komeda_pipeline *pipe; 18 19 if (mdev->n_pipelines + 1 > KOMEDA_MAX_PIPELINES) { 20 DRM_ERROR("Exceed max support %d pipelines.\n", 21 KOMEDA_MAX_PIPELINES); 22 return NULL; 23 } 24 25 if (size < sizeof(*pipe)) { 26 DRM_ERROR("Request pipeline size too small.\n"); 27 return NULL; 28 } 29 30 pipe = devm_kzalloc(mdev->dev, size, GFP_KERNEL); 31 if (!pipe) 32 return NULL; 33 34 pipe->mdev = mdev; 35 pipe->id = mdev->n_pipelines; 36 pipe->funcs = funcs; 37 38 mdev->pipelines[mdev->n_pipelines] = pipe; 39 mdev->n_pipelines++; 40 41 return pipe; 42 } 43 44 void komeda_pipeline_destroy(struct komeda_dev *mdev, 45 struct komeda_pipeline *pipe) 46 { 47 struct komeda_component *c; 48 int i; 49 50 dp_for_each_set_bit(i, pipe->avail_comps) { 51 c = komeda_pipeline_get_component(pipe, i); 52 komeda_component_destroy(mdev, c); 53 } 54 55 clk_put(pipe->pxlclk); 56 clk_put(pipe->aclk); 57 58 of_node_put(pipe->of_output_dev); 59 of_node_put(pipe->of_output_port); 60 of_node_put(pipe->of_node); 61 62 devm_kfree(mdev->dev, pipe); 63 } 64 65 struct komeda_component ** 66 komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id) 67 { 68 struct komeda_dev *mdev = pipe->mdev; 69 struct komeda_pipeline *temp = NULL; 70 struct komeda_component **pos = NULL; 71 72 switch (id) { 73 case KOMEDA_COMPONENT_LAYER0: 74 case KOMEDA_COMPONENT_LAYER1: 75 case KOMEDA_COMPONENT_LAYER2: 76 case KOMEDA_COMPONENT_LAYER3: 77 pos = to_cpos(pipe->layers[id - KOMEDA_COMPONENT_LAYER0]); 78 break; 79 case KOMEDA_COMPONENT_WB_LAYER: 80 pos = to_cpos(pipe->wb_layer); 81 break; 82 case KOMEDA_COMPONENT_COMPIZ0: 83 case KOMEDA_COMPONENT_COMPIZ1: 84 temp = mdev->pipelines[id - KOMEDA_COMPONENT_COMPIZ0]; 85 if (!temp) { 86 DRM_ERROR("compiz-%d doesn't exist.\n", id); 87 return NULL; 88 } 89 pos = to_cpos(temp->compiz); 90 break; 91 case KOMEDA_COMPONENT_SCALER0: 92 case KOMEDA_COMPONENT_SCALER1: 93 pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]); 94 break; 95 case KOMEDA_COMPONENT_IPS0: 96 case KOMEDA_COMPONENT_IPS1: 97 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0]; 98 if (!temp) { 99 DRM_ERROR("ips-%d doesn't exist.\n", id); 100 return NULL; 101 } 102 pos = to_cpos(temp->improc); 103 break; 104 case KOMEDA_COMPONENT_TIMING_CTRLR: 105 pos = to_cpos(pipe->ctrlr); 106 break; 107 default: 108 pos = NULL; 109 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id); 110 break; 111 } 112 113 return pos; 114 } 115 116 struct komeda_component * 117 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id) 118 { 119 struct komeda_component **pos = NULL; 120 struct komeda_component *c = NULL; 121 122 pos = komeda_pipeline_get_component_pos(pipe, id); 123 if (pos) 124 c = *pos; 125 126 return c; 127 } 128 129 /** komeda_component_add - Add a component to &komeda_pipeline */ 130 struct komeda_component * 131 komeda_component_add(struct komeda_pipeline *pipe, 132 size_t comp_sz, u32 id, u32 hw_id, 133 struct komeda_component_funcs *funcs, 134 u8 max_active_inputs, u32 supported_inputs, 135 u8 max_active_outputs, u32 __iomem *reg, 136 const char *name_fmt, ...) 137 { 138 struct komeda_component **pos; 139 struct komeda_component *c; 140 int idx, *num = NULL; 141 142 if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) { 143 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n", 144 max_active_inputs); 145 return NULL; 146 } 147 148 pos = komeda_pipeline_get_component_pos(pipe, id); 149 if (!pos || (*pos)) 150 return NULL; 151 152 if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) { 153 idx = id - KOMEDA_COMPONENT_LAYER0; 154 num = &pipe->n_layers; 155 if (idx != pipe->n_layers) { 156 DRM_ERROR("please add Layer by id sequence.\n"); 157 return NULL; 158 } 159 } else if (has_bit(id, KOMEDA_PIPELINE_SCALERS)) { 160 idx = id - KOMEDA_COMPONENT_SCALER0; 161 num = &pipe->n_scalers; 162 if (idx != pipe->n_scalers) { 163 DRM_ERROR("please add Scaler by id sequence.\n"); 164 return NULL; 165 } 166 } 167 168 c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL); 169 if (!c) 170 return NULL; 171 172 c->id = id; 173 c->hw_id = hw_id; 174 c->reg = reg; 175 c->pipeline = pipe; 176 c->max_active_inputs = max_active_inputs; 177 c->max_active_outputs = max_active_outputs; 178 c->supported_inputs = supported_inputs; 179 c->funcs = funcs; 180 181 if (name_fmt) { 182 va_list args; 183 184 va_start(args, name_fmt); 185 vsnprintf(c->name, sizeof(c->name), name_fmt, args); 186 va_end(args); 187 } 188 189 if (num) 190 *num = *num + 1; 191 192 pipe->avail_comps |= BIT(c->id); 193 *pos = c; 194 195 return c; 196 } 197 198 void komeda_component_destroy(struct komeda_dev *mdev, 199 struct komeda_component *c) 200 { 201 devm_kfree(mdev->dev, c); 202 } 203