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